/*
 * Copyright (C) 1999-2006 <a href="mailto:adrian.paschke@gmx.de">Adrian Paschke</a>
 * 
 * The RBSLM Environment is part of the Rule Based Service Level Agreement (RBSLA)
 * framework, available at 
 * <a href=" http://ibis.in.tum.de/staff/paschke/rbsla/index.htm">RBSLA</a>
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package rbsla.environment;

import java.awt.Frame;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import rbsla.wrapper.ProvaWrapper;
import rbsla.environment.view.ActiveRulesViewer;
import rbsla.environment.view.ViewDialog;
import rbsla.environment.view.ViewModell;
import rbsla.environment.view.Viewer;

/**
 * Updates the modell with new values from the knoledgebase.
 *  
 */
public class StartViewDaemon extends Object implements Runnable
{
    private static StartViewDaemon startViewDaemonDefault;

    private static int PROCESS_CHECKINTERVAL = 1000;

    private ProvaWrapper myProva = null;

    private List viewList = new ArrayList();

    private Class thisClass = StartViewDaemon.class;

    private boolean doAbort = false;

    private String projectFileName;

    private static Logger logger = Logger.getLogger(StartViewDaemon.class);
    
    public StartViewDaemon()
    {
    }

    public synchronized static StartViewDaemon initialise()
    {
        if (startViewDaemonDefault == null)
        {
            StartViewDaemon instance = new StartViewDaemon();
            Thread thread = new Thread(instance, "ECA_ENVIRONMENT");
            thread.setDaemon(true);
            thread.setPriority(Thread.MIN_PRIORITY);
            thread.start();
            // Zeile ist wichig, falls zwei Methoden gleichzeitig getInstance
            // aufrufen
            startViewDaemonDefault = instance;
        }
        return startViewDaemonDefault;
    }

    public synchronized static StartViewDaemon getInstance()
    {
        return startViewDaemonDefault;
    }

    public void addView(ViewModell viewModell, Frame parent)
    {

        if (!viewList.contains(viewModell))
        {
            viewList.add(viewModell);
        }
            try
            {
                String viewerClassName = viewModell.getViewerClassName();
                Viewer viewerInterface = (Viewer) Class
                        .forName(viewerClassName).newInstance();
                ViewDialog view = new ViewDialog((ECAWindow) parent,
                        viewModell, viewerInterface);

            } catch (Exception ex)
            {
                logger.info("", ex);
            }

    }

    public void deleteView(ViewModell view)
    {
        viewList.remove(view);
    }

    public void abort()
    {
        doAbort = true;
    }

    public void reloadProva(ProvaWrapper myProva)
    {
        //this.myProva = null;
        this.myProva = myProva;
    }

    public void loadViews(Frame parent, String _projectFileName)
    {
        projectFileName = _projectFileName;

        if (projectFileName == null || projectFileName.equals(""))
            projectFileName = ECAConstraints._FILE_BASE_PATH + "default.project";

        try
        {

            List viewListLoaded = new ArrayList();

            FileInputStream fileIn = new FileInputStream(projectFileName);
            ObjectInputStream in = new ObjectInputStream(fileIn);

            logger.info("Loading Hashtable Object...");
            viewListLoaded = (List) in.readObject();

            logger.info("Closing all input streams...\n");
            in.close();
            fileIn.close();

            for (int i = 0; i < viewListLoaded.size(); i++)
                this.addView((ViewModell) viewListLoaded.get(i), parent);

            logger.info("Creating File/Object input stream...");

        } catch (ClassNotFoundException e)
        {
            logger.info("", e);
        } catch (FileNotFoundException e)
        {
            logger.info("", e);
        } catch (IOException e)
        {
            logger.info("", e);
        }
    }
    
    public void run()
    {
        try
        {
            while (!doAbort)
            {
                for (int i = 0; i < viewList.size(); i++)
                {
                    ViewModell viewModell = (ViewModell) viewList.get(i);
                    String query = viewModell.getQuery();
                    String result = "", debugText = "";
                    if (myProva != null)
                    {
                        StringWriter debugWriter = new StringWriter();
                        result = ((ProvaWrapper)myProva.createChild()).getResultStrings(query);
                        debugText = debugWriter.toString();
                    }
                    viewModell.setResult(result, debugText);

                }
                Thread.currentThread().sleep(this.PROCESS_CHECKINTERVAL);
            }
        } catch (Exception ex)
        {
            logger.info("", ex);

        }

        save();

        System.exit(1);
    }

    private void save()
    {
        try
        {
            for (int i = 0; i < viewList.size(); i++)
            {
                ViewModell viewModell = (ViewModell) viewList.get(i);
                viewModell.notifyDataChange();
            }
            logger.info("Creating File/Object output stream...");

            FileOutputStream fileOut = new FileOutputStream(projectFileName,
                    false);
            ObjectOutputStream out = new ObjectOutputStream(fileOut);

            logger.info("Writing Hashtable Object...");
            out.writeObject(viewList);

            logger.info("Closing all output streams...\n");
            out.close();
            fileOut.close();

        } catch (FileNotFoundException ex)
        {
            logger.info("", ex);
        } catch (IOException ex)
        {
            logger.info("", ex);
        }
    }
    
}