package arrival_generator;

import generating.JobLogger;
import probability_distribution.UniformDist;
import probability_distribution.ExponentialDist;
import probability_distribution.ProbabilityDist;
import mapping.Mapper;
import mapping.data.JobClass;

/**
 * 
 * This class uses the exponential and uniform probability distributions to estimate arrival times and executionTime
 * for a given job class respectively.
 * 
 * 
 * @author Ben Kybartas
 *
 */
public class EXP_AND_UNI_AG extends ArrivalGenerator
{

	/**
	 * @see ExponentialDist#probability_distribution
	 */
	private ProbabilityDist probabilitydist;
	
	/**
	 * @see UniformDist#probability_distribution
	 */
	private ProbabilityDist variationDistribution;
	
	/**
	 * The current mapper being used
	 */
	private Mapper mapper;
	
	/**
	 * The job class for which the arrival rates and execution times are being calculated
	 */
	private JobClass jobclass;
	
	/** A logger which is used to log jobs specifically for FILE_READ_AG */
	private JobLogger jobLogger;
	
	/**
	 * 
	 * @param jobClass
	 * 				The jobClass for which the execution times and arrival rates should be calculated
	 * @param mapper
	 * 				The current mapper being used
	 */
	public EXP_AND_UNI_AG(JobClass jobClass, Mapper mapper)
	{
		String filename;
		
		this.setMapper(mapper);
		this.setDescription("EXP_AND_UNI_AG");
		this.setJobClass(jobClass);

		filename = new String("JobClass" + jobClass.getIndex());
		this.setJobLogger(new JobLogger(filename, jobClass.getIndex()));
		
		this.setProbabilityDist(new ExponentialDist(this.getJobClass().getArrivalRate()
				/ (this.getMapper().getTimeUnitInMinutes() * 60.0 * 1000.0)));
		
		this.setVariationDistribution(new UniformDist(0.05));; //0.5 is default value

	}
	
	protected void setJobLogger(JobLogger joblogger)
	{
		this.jobLogger = joblogger;
	}
	
	protected JobLogger getJobLogger()
	{
		return this.jobLogger;
	}
	
	protected Mapper getMapper()
	{
		return this.mapper;
	}
	
	protected void setMapper(Mapper mapper)
	{
		this.mapper = mapper;
	}
	
	protected JobClass getJobClass()
	{
		return this.jobclass;
	}
	
	protected void setJobClass(JobClass jobClass)
	{
		this.jobclass = jobClass;
	}
	
	protected ProbabilityDist getProbabilityDist()
	{
		return this.probabilitydist;
	}
	
	protected void setProbabilityDist(ProbabilityDist probabilityDist)
	{
		this.probabilitydist = probabilityDist;
	}
	
	public ProbabilityDist getVariationDistribution() 
	{
		return variationDistribution;
	}

	public void setVariationDistribution(ProbabilityDist variationDistribution) 
	{
		this.variationDistribution = variationDistribution;
	}
	
	/**
	 * The logger should be closed when the job generators are stopped
	 */
	public void closeLogger()
	{
		this.getJobLogger().closeStreams();
	}
	
	public long[] getNextJobInfo()
	{
		long[] JobInfo = new long[3];
		long JobClass;
		long ArrivalTime;
		long executionTime;
		
		
		JobClass = (long) this.getJobClass().getIndex();
		ArrivalTime = (long) this.getProbabilityDist().FInverse();
		executionTime = (long) Math.round(this.getVariationDistribution().FInverse() * this.getJobClass().getexecutionTime()
				+ this.getJobClass().getexecutionTime());
		
		JobInfo[0] = JobClass;
		JobInfo[1] = ArrivalTime;
		JobInfo[2] = executionTime;
		
		this.getJobLogger().logJob(JobInfo[1], JobInfo[2]);
		
		return JobInfo;
	}
}
