/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package qsim.simulators;

/**
 *
 * @author joe
 */
import gui.ErrorDialog;
import qsim.stat.*;
import java.util.ArrayList;
import java.util.List;
import umontreal.iro.lecuyer.probdist.ContinuousDistribution;
import umontreal.iro.lecuyer.simevents.*;
import umontreal.iro.lecuyer.simprocs.*;
import umontreal.iro.lecuyer.rng.*;
import umontreal.iro.lecuyer.randvar.RandomVariateGen;

public class QueueProc extends QueueMotor{

    private Resource server;

    private List<Double> dataFromTime = new ArrayList<Double>();
    private List<Double> dataFromEvent = new ArrayList<Double>();
    private double valaszIdo = 0.0;
    public BatchMeansMethod bm;

    public QueueProc(ContinuousDistribution arrDist, ContinuousDistribution servDist, int n, String policy, double timeHorizon) {

        //szerver inicializálása
        this.arrDist = arrDist;
        this.servDist = servDist;
        this.n = n;
        server = new Resource(n, "Kiszolgáló");

        //seedek inicializalasa
        long[] genArrSeed = {Math.round(Math.random() * 100000), Math.round(Math.random() * 100000), Math.round(Math.random() * 100000),
            Math.round(Math.random() * 100000), Math.round(Math.random() * 100000), Math.round(Math.random() * 100000)
        };
        long[] genServSeed = {Math.round(Math.random() * 100000), Math.round(Math.random() * 100000), Math.round(Math.random() * 100000),
            Math.round(Math.random() * 100000), Math.round(Math.random() * 100000), Math.round(Math.random() * 100000)
        };


        //eloszlások inicializálása
        MRG32k3a arrRng = new MRG32k3a();
        arrRng.setSeed(genArrSeed);
        MRG32k3a servRng = new MRG32k3a();
        arrRng.setSeed(genServSeed);

        genArr = new RandomVariateGen(arrRng, arrDist);
        genServ = new RandomVariateGen(servRng, servDist);

        //kiszolgálási elv
        this.policy = new String(policy);
        if (policy.equals("LIFO")) {
            server.setPolicyLIFO();
        }
        this.timeHorizon = timeHorizon;

    }

    public ContinuousDistribution getArrDist() {
        return arrDist;
    }

    public ContinuousDistribution getServDist() {
        return servDist;
    }

    /**
     * Ez az osztály főmetódusa, ami a szimulációt végrehajtja.
     */
    private void simulateOneRun() {
        SimProcess.init();

        server.setStatCollecting(true);
        //server.init(); //server inicializálása - KELL?!
        new EndOfSim().schedule(timeHorizon);
        new Customer().schedule(genArr.nextDouble());
        new DataFromTimeGeatherer(dataFromTime).schedule(0.1);

        Simulator.getDefaultSimulator().start();
    }

    private class Customer extends SimProcess {

        @Override
        public void actions() {
            new Customer().schedule(genArr.nextDouble());
            server.request(1);
            delay(genServ.nextDouble());
            server.release(1);

            collectSojourn();
        }
    }

    private class EndOfSim extends Event {

        @Override
        public void actions() {
            Simulator.getDefaultSimulator().stop();
        }
    }

    private class DataFromTimeGeatherer extends Event {

        private List<Double> res;

        public DataFromTimeGeatherer(List res) {
            this.res = res;
        }

        @Override
        public void actions() {
            res.add((double) (server.waitList().size() + (server.getAvailable() == 0 ? 0 : server.getCapacity() - server.getAvailable())));
            new DataFromTimeGeatherer(res).schedule(0.1);
        }
    }

    public void generateChart(String chartType, int batchSize, double confidenceLevel, String chartTitle) {

        if (chartType.equals("sojourn")) {
            new BatchMeansMethod(dataFromEvent, batchSize, confidenceLevel, chartTitle).drawBachmeansChart();
        } 
        else if (chartType.equals("queueSize")) {
            new BatchMeansMethod(dataFromTime, batchSize, confidenceLevel, chartTitle).drawBachmeansChart();
        }
        else{
            new ErrorDialog(null, true, "Nem támogatott grafikon!");
        }
    }

    /**
     * Ez hívódik meg ... 
     */
    public String getSimResult() {
        this.simulateOneRun();
        return this.server.report();
    }
    //stisztika gyűjtő metódusok:
    private void collectSojourn() {
        dataFromEvent.add(server.statOnSojourn().sum() - valaszIdo);
        valaszIdo = server.statOnSojourn().sum();
    }
}
