/*
 *  T-Mass simulation calendar 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.jTMassSimulator.jTCalendar;

import jTGUI.TCalendarPanel;
import jTMass.TMass;
import jTMass.core.jTMassModel.TModelElement;
import java.io.FileWriter;
import java.util.LinkedList;

public class TCalendar {

    private int PActive=0;
    private final static int _HistorySize=1000;
    private LinkedList<TCalendarEvent> PCalendar;
    private LinkedList<TCalendarEvent> PCalendarHistory;
    private TCalendarPanel PCalendarPanel=null;
    private TCalendarPanel PCalendarHistoryPanel=null;
    private FileWriter PSwapFile;

    // ===== GUI =====

    public void setPanels(TCalendarPanel calendar, TCalendarPanel history){
        PCalendarPanel=calendar;
        PCalendarHistoryPanel=history;
    }

    public void refreshPanels(){
        if(!TMass.simulationRunning()){
            if(PCalendarPanel!=null)
                PCalendarPanel.setCalendar();
            if(PCalendarHistoryPanel!=null)
                PCalendarHistoryPanel.setCalendar();
        }
    }

    // ===== EVENT AND HISTORY LISTS ACCESSES =====

    public int getSize(){
        return PCalendar.size();
    }

    public boolean isEmpty(){
        return(PCalendar.size()==0);
    }

    public void addToHistoryList(TCalendarEvent event){
        TCalendarEvent oldEvent;
        if(PCalendarHistory.size()>_HistorySize){
            for(int i=0;i<(_HistorySize/2);i++){
                oldEvent=PCalendarHistory.get(0);
                try{
                    PSwapFile.append(oldEvent.getFireTimeS()+";"+oldEvent.getElementS()+";"+
                            oldEvent.getEventTypeS()+";"+oldEvent.getGeneratedBy()+";"+
                            oldEvent.getGenTimeS()+"\n");
                    PSwapFile.flush();
                }catch(Exception e){
                    TMass._Terminal.reportError("Simulator, writting to swap file");
                }
                PCalendarHistory.remove(0);
            }
        }
        PCalendarHistory.add(event);
        return;
    }

    public LinkedList<TCalendarEvent> getEventList(){
        return(PCalendar);
    }

    public LinkedList<TCalendarEvent> getHistoryList(){
        return(PCalendarHistory);
    }

    // ===== CALENDAR EVENTS ACCESS METHORS =====

    public boolean containsEventFor(TModelElement element){
        if(PCalendar.size()==0)
            return(false);

        for(TCalendarEvent event:PCalendar)
            if(event.getElement()==element)
                return(true);

        return(false);
    }

    public long getFirstEventTime(){
        if(PCalendar.size()==0)
            return(-1);   // no events
        else
            return(PCalendar.get(0).getFireTime());
    }

    public long getLastEventTime(){
        if(PCalendar.size()==0)
            return(-1);   // no events
        else
            return(PCalendar.get(PCalendar.size()-1).getFireTime());
    }
    
    public TCalendarEvent getFirstEvent(){
        if(PCalendar.size()==0)
            return(null);
        else{
            PActive=0;
            return(PCalendar.get(0));
        }
    }

    public TCalendarEvent getNextEvent(){
        if(PCalendar.size()<=(PActive+1))
            return(null);
        else{
            PActive++;
            return(PCalendar.get(PActive));
        }
    }

    public void insertEvent(TCalendarEvent event){
        int i=0;
        
        if(PCalendar.size()==0){
            PCalendar.add(0,event);

            if(PCalendarPanel!=null){
                PCalendarPanel.setCalendar();
                PCalendarHistoryPanel.setCalendar();
            }

            return;
        }

        Long execTime=event.getFireTime();

        while((i<PCalendar.size())&&(PCalendar.get(i).getFireTime()<=execTime)){
            TCalendarEvent oldEvent=PCalendar.get(i);
            if((((Long)oldEvent.getFireTime()).equals(event.getFireTime()))&&
                                        (oldEvent.getElement()==event.getElement())){
                    
                oldEvent.setEventType(oldEvent.getEventType()|event.getEventType());
                return;
            }
            i++;
        }
            
        PCalendar.add(i,event);
        if(PCalendarPanel!=null){
            PCalendarPanel.setCalendar();
            PCalendarHistoryPanel.setCalendar();
        }
    }

    public void insertEvent(TModelElement element, int eventType,
               Long gTime, Long eTime, TModelElement source){
        insertEvent(
            new TCalendarEvent(element, eventType, gTime, eTime, source));
    }

    public void insertEvent(TModelElement element, int eventType, Long eTime){
        insertEvent(new TCalendarEvent(element, eventType, TMass.getSimulator().getModelTime(),
                eTime, TMass.getSimulator()));
    }

    public void deleteEvent(TCalendarEvent event){
        PCalendar.remove(event);
        addToHistoryList(event);
        if(PCalendarPanel!=null){
            PCalendarPanel.setCalendar();
            PCalendarHistoryPanel.setCalendar();
        }
        return;
    }

    public TCalendarEvent getEventAfter(Float time){
        int i=0;

        while((PCalendar.get(i).getFireTime()<time)&&(++i<PCalendar.size()));
        if(PCalendar.size()==i)
            return(null);
        else
            return(PCalendar.get(i));
    }

    public void eraseCalendar(){
        PCalendar.clear();
        PCalendarHistory.clear();
        if(PCalendarPanel!=null){
            PCalendarPanel.setCalendar();
            PCalendarHistoryPanel.setCalendar();
        }
    }

    // ===== CONSTRUCTOR =====

    public TCalendar(){
        PCalendar=new LinkedList<TCalendarEvent>();
        PCalendarHistory=new LinkedList<TCalendarEvent>();
        try{
            PSwapFile=new FileWriter(TMass.getModelPath()+"/swap/.#calendarhistory.swh");
        }catch(Exception e){
            TMass._Terminal.reportError("Cannot create calendar wwap file");
            PSwapFile=null;
        }
    }

}
