/*
 *  T-Mass main 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;
import jTGUI.TBackgroundFrame;
import jTMass.core.jTMassModel.*;
import jTMass.core.jTMassSimulator.TSimulator;
import jTMass.core.jLoaders.TModelLoader;
import jTMass.core.jTMassSimulator.jTCalendar.TCalendar;
import java.io.File;
import javax.swing.JFrame;

public class TMass{

    /*
     * V08 - vylepseni
     */

    private static String PVersion = "0.M.01";
    protected static TSimulator PSimulator;
    private static TModel PModel;
    public static TTerminal _Terminal;
    public static TMass _TMass;
    public static TModelLoader _Loader;
    public static TBackgroundFrame PMainFrame;
    public static boolean PRunning=false;
    public static String PModelFileName="";

    // ===== SIMULATION TYPE / BREAKPOINTS =====
    protected static final int _STT_Go=0;
    protected static final int _STT_Steps=1;
    protected static final int _STT_Time=2;
    protected static final int _STT_None=3;

    static protected TSimulationThread PSimThread;
    static protected int PTermination=_STT_None;
//    static Long PEventsExecuted=new Long(0);
    static public Long PSystemDeadline=new Long(100000);
    static protected Long PDeadline=new Long(0);
    static protected int PStepsToGo=0;

    // ===== READERS/WRITERS =====

    public static String getVersion() {
        return PVersion;
    }

    public static TSimulator getSimulator(){
    	return(PSimulator);
    }
    
    public static TModel getModel(){
    	return(PModel);
    }

    public static String getModelPath(){
        File modelFile=new File(PModelFileName);
        return(modelFile.getParent());
    }

    public static boolean simulationRunning(){
        TCalendar calendar=getSimulator().getCalendar();
        return(((!calendar.isEmpty())&&
                ((calendar.getFirstEventTime()<PDeadline)||(PTermination!=_STT_Time))&&
                ((PStepsToGo>=1)||(PTermination!=_STT_Steps))&&
                (calendar.getFirstEventTime()<PSystemDeadline)));
    }

    public static TBackgroundFrame getPMainFrame() {
        return PMainFrame;
    }

    public Long getDeadline(){
        return(PSystemDeadline);
    }

    public void setDeadline(Long deadline){
        PSystemDeadline=deadline;
    }

    // ===== INIT SIMULATION =====

    static void runSimulation(){
        
        TCalendar calendar=PSimulator.getCalendar();
        PSimThread=new TSimulationThread();
        PSimThread.start();
        getSimulator().getCalendar().refreshPanels();
    }

    public static void startSimulation(String steps){

        TMass._Terminal.printlnSystemInfo("Starting Simulation: "+steps);
        try{
            if(steps.compareToIgnoreCase("Go!")==0){
                PTermination=_STT_Go;
                TMass._Terminal.printlnSystemInfo("PROCESSING SIM ACL / REQUEST GO");
            }
            else
            if(PMainFrame.getSimMode()==TBackgroundFrame._SM_Steps)
            {
                PTermination=_STT_Steps;
                PStepsToGo=Integer.parseInt(steps);
                TMass._Terminal.printlnSystemInfo("PROCESSING SIM ACL / REQUEST STEPS "+PStepsToGo);

            }
            else
            if(PMainFrame.getSimMode()==TBackgroundFrame._SM_Time)
            {
                PTermination=_STT_Time;
                PDeadline=PSimulator.getModelTime()+Integer.parseInt(steps);
                TMass._Terminal.printlnSystemInfo("PROCESSING SIM ACL / REQUEST STEPS "+PStepsToGo);
            }

        }
        catch(Exception e){
            TMass._Terminal.reportError("Start simulation, param="+steps);
        }

        PMainFrame.simulationSarted();
        runSimulation();
        return;
    }

    public static void pauseSimulation(){
        if(PSimThread!=null)
            PSimThread.stop();
        PMainFrame.simulationPaused();
    }

    // ===== MODEL LOADER =====

    public void loadModel(String modelFile){
        try{
//            PEventsExecuted=new Long(0);
            PModelFileName=modelFile;
            try{
                File mf=new File(PModelFileName);
                String filePath=mf.getParent()+File.separator+"swap";
                File dir=new File(filePath);
                dir.mkdirs();
            }
            catch(Exception e){
                TMass._Terminal.reportError("Cannot create swap directorys");
            }
            TModelLoader loader=new TModelLoader(modelFile);
            PModel=loader.getModel();
            PSimulator=new TSimulator("TMassM Sim v0.1",PModel);
            PModel.addElement(PSimulator);
            PSimulator.initElement(new TCalendar());
            PMainFrame.loadUniverse();
            PMainFrame.enableComponents();
            TModelLoader._PFilePath=System.getProperty("user.dir");
            this.PMainFrame.setTitle("TMass-M "+"("+this.getModel().getModelName()+")");

            TMass._Terminal.printlnSystemInfo(
                "==^==^==^==^==^==^==^==^== MODEL LOADED ==^==^==^==^==^==^==^==^==");
            PMainFrame.simulationPaused();
        }
        catch(Exception e){
            TMass._Terminal.reportError("Load model file '"+modelFile+"'");
        }
    }

    public void reloadModel(){
        loadModel(PModelFileName);
        PMainFrame.loadUniverse();
    }


    // ======================================================================
    //   T-Mass Constructors
    // ======================================================================

    public TMass() {
    	PModel=new TModel();
    	PSimulator=null;
        PMainFrame=new TBackgroundFrame(this);
        PMainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        PMainFrame.setVisible(true);
        _Terminal = new TTerminal(PMainFrame);
    }
	
    public TMass(String inputFile){
        PMainFrame=new TBackgroundFrame(this);
        PMainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
        PMainFrame.setVisible(true);
        _Terminal = new TTerminal(PMainFrame);
        loadModel(inputFile);
    }

    // ===== MAIN =====
    
    public static void main(String[] args) {
             if(args.length>0)
                	_TMass = new TMass(args[0]);
                else
                	_TMass = new TMass();
	};
}