/*
 *  Platform computation unit (PCU) class
 *
 *  2004 - 2011 Frantisek Zboril jr.
 *  Faculty of Information Technology
 *  zborilf@fit.vutbr.cz
 *  http://www.fit.vutbr.cz/~zborilf
 *
 * (C) Brno University of Technology
 * Freeware licence VUT v Brně
 * https://wis.fit.vutbr.cz/FIT/db/dir.php/dr/VZ2007/externiInformace/softwareNaWebu/Priloha2_rozh23.pdf

 */

package jTMass.core.jTMassPlatform;

import java.util.Hashtable;
import java.util.Iterator;

import jTMass.TMass;
import jTMass.core.jTMassPlatform.jTServices.TAService;
import jTMass.core.jALLL.jTObjects.TList;
import jTMass.core.jALLL.jTObjects.TObject;
import jTMass.core.jTMassModel.jModelData.TSpeechAct;
import jTMass.core.jTMassPlatform.jTServices.TASAsynchronousService;
import jTMass.core.jTMassPlatform.jTServices.TASSynchronousService;
import java.lang.reflect.Constructor;
import java.util.LinkedList;

public class TPCU {
	
    private Hashtable<String, Constructor> PServices;
    private LinkedList<TASAsynchronousService> PActiveServices;
    private Hashtable<String, TObject> PPlatformVariables;
    private TPlatform PPlatform;
    private Hashtable<String,LinkedList<TSpeechAct>> PServiceMessagesBuffer=
            new Hashtable<String, LinkedList<TSpeechAct>>();

   // ===== CLONING =====

    protected Hashtable<String, Constructor> cloneServices(){
        return((Hashtable<String, Constructor>)PServices.clone());
    }

    protected Hashtable<String, TObject> cloneVariables(){
        return((Hashtable<String, TObject>)PPlatformVariables.clone());
    }

    // ===== TERMINAL =====

    public void printServices(){
        Object key;
	Iterator keys=PServices.keySet().iterator();

        while(keys.hasNext()){
            key=keys.next();
            TMass._Terminal.printlnDebug("Service "+key+" performed by "+
                    PServices.get((String)key).toString());
	}
    }

    // ===== PLATFORM VARIABLES =====

    public Hashtable<String,TObject> getVariables(){
        return(PPlatformVariables);
    }

    public TObject getVariable(String variableName){
        return(PPlatformVariables.get(variableName));
    }

    public void setVariables(Hashtable<String,TObject> variables){
        PPlatformVariables=variables;
        PPlatform.refreshVRPanel();
    }

    public void addVariable(String varName, TObject varValue){
        PPlatformVariables.put(varName, varValue);
        PPlatform.refreshVRPanel();
    }

    public void addVariable(String varName){
        addVariable(varName, null);
        PPlatform.refreshVRPanel();
    }

    // ===== PLATFORM SERVICES =====

    public String getServicesS(){
        String result="";
        
        for(String service:PServices.keySet()){
            if(!result.contentEquals(""))
                result=result+",";
            
            result=result+service;
        }
        
        return(result);
    }

    public int getnoActiveServices(){
        return(PActiveServices.size());
    }

    public LinkedList<TASAsynchronousService> getActiveServices(){
        return(PActiveServices);
    }

    public Hashtable<String, Constructor> getServices(){
        return(PServices);
    }


    public boolean addService(String serviceName, Constructor service){
        PServices.put(serviceName, service);
	return(true);
    }

    protected boolean setServices(Hashtable<String, Constructor> newServices){
        PServices=newServices;
	return(true);
    }

    protected boolean serviceExists(String service_name){
        return(PServices.containsKey(service_name));
    }

    protected TASAsynchronousService getService(String service_name){
        for(TASAsynchronousService service:PActiveServices)
            if(service.getServiceName().contentEquals(service_name))
                return(service);
        return(null);
    }
	
    // ===== ACTIVE SERVICES, EXECUTION =====

    protected void storeActiveService(TASAsynchronousService service){
        PActiveServices.add(service);
        PPlatform.refreshASPanel();
        PServiceMessagesBuffer.put(service.getServiceName(), new LinkedList<TSpeechAct>());
    }

    protected void deleteActiveService(TASAsynchronousService service){
        PServiceMessagesBuffer.remove(service.getServiceName());
        PActiveServices.remove(service);
    }

    public boolean storeMessage(TSpeechAct act){
        if(PServiceMessagesBuffer.containsKey(act.getInReplyTo()))
        {
           PServiceMessagesBuffer.get(act.getInReplyTo()).addLast(act);
           return(true);
        }
        return(false);
    }

    public LinkedList<TSpeechAct> getMessages(TASAsynchronousService service){
        return(PServiceMessagesBuffer.get(service.getServiceName()));
    }

    protected void runActiveServices(){
        int i=0;
        TASAsynchronousService service;

        while(i<PActiveServices.size()){
            service=PActiveServices.get(i);
            if(service.isTime())
                if(!service.reviveService()){
                    // service finished
                    deleteActiveService(service);
                    PPlatform.serviceFinished(service);
                    PPlatform.refreshASPanel();
                    i--;
                }
            i++;
        }
    }
	
    protected TObject runService(String serviceName, TList parameters, String clientName, TPlatform platform){
        try{
            Object[] params=new Object[1];
            params[0]=platform;
            TAService service=(TAService)PServices.get(serviceName).newInstance((java.lang.Object[])params);
            if(service!=null){
                String serviceInstanceName=serviceName+"."+clientName+"."+
                            String.valueOf(TMass.getSimulator().getModelTime());
                TObject result=service.processService(parameters, clientName, serviceInstanceName);
                // if(service instanceof TSDeamon) runandSet ...
                if (service instanceof TASSynchronousService){
                    platform.serviceFinished(service);
                    platform.runandSet(clientName,result);
                }
            return(result);
        }
        else
            return(null);

        }catch(Exception e){
            TMass._Terminal.reportError("Service execution failed");
        }
        return(null);
    }

    public boolean terminateService(String serviceName){
        TASAsynchronousService service=getService(serviceName);
        if(service!=null){
            deleteActiveService(service);
            PPlatform.serviceFinished(service);
            PPlatform.refreshASPanel();
            return(true);
        }
        else{
            TMass._Terminal.reportError("Service termination failed");
            return (false);
        }
    }

    // ===== CONSTRUCTOR =====
	
    protected TPCU(TPlatform platform){
        PServices=new Hashtable<String, Constructor> ();
        PActiveServices=new LinkedList<TASAsynchronousService>();
        PPlatformVariables=new Hashtable<String,TObject>();
        PPlatform=platform;
    }

}