/**
 * COMP2240 Assignment 1
 * Date: 28/08/21
 * Author: Zach S-B
 * Student Number: c3262201
 */

import java.util.*;
import java.io.*;

public class A1 {
    //Address of File name relative to code. Replace with request for filename?
    String fileName = "datafiles/datafile1.txt";
    
    LinkedList<Process> processList = new LinkedList<Process>();
    LinkedList<Integer> randomNum = new LinkedList<>();

    //Initialise Dispatcher time variable
    int disp;

    /**
     * Main. Runs the program
     */
    public static void main(String[] args){
        A1 system = new A1();
        system.run();
    }

    /**
     * Run. Most of the program starts from here.
     */
    public void run()
    {
        System.out.println("COMP2240 - Assignment 1 \nAuthor: Zach S-B \nStudent# :c3262201");   
        System.out.println("NOTE: See comment on the moveQueues function, short version is its broken");

        //Store results for final print in these arrays. [0] is turnaround average, [1] is waiting time average
        double[] fcfsResults = new double[2];
        double[] srtResults = new double[2];
        double[] fbvResults = new double[2];
        double[] ltrResults = new double[2];

        readFile();

        Algorithm fcfs = new Algorithm(disp, processList, randomNum, "FCFS");
        fcfs.runDispatch();
        fcfsResults[0] = fcfs.averageTurnTime();
        fcfsResults[1] = fcfs.averageWaitTime();
        printResults();
        reset();

        System.out.println();

        Algorithm srt = new Algorithm(disp, processList, randomNum,"SRT");
        srt.runDispatch();
        srtResults[0] = srt.averageTurnTime();
        srtResults[1] = srt.averageWaitTime();        
        printResults();
        reset();

        Algorithm fbv = new Algorithm(disp, processList, randomNum,"FBV");
        fbv.runDispatchFBV();
        fbvResults[0] = fbv.averageTurnTime();
        fbvResults[1] = fbv.averageWaitTime();        
        printResults();
        reset();        

        System.out.println();

        Algorithm ltr = new Algorithm(disp, processList, randomNum,"LTR");
        ltr.runDispatch();
        ltrResults[0] = ltr.averageTurnTime();
        ltrResults[1] = ltr.averageWaitTime();         
        printResults();
        reset();   
        
        printAverages(fcfsResults, srtResults, fbvResults, ltrResults);

    }

    public void reset()
    {  
        for(int i = 0; i < processList.size(); i++)
        {
            processList.get(i).reset();
        }
    }

    /**
     * Prints out the averages of each algorithm. It assumes each one has been run at least once.
     * @param fcfs First Come Firs Serve, assumes first value in array is Turn around time, and second is the Waiting Time
     * @param srt Shortest Remaining Time, assumes first value in array is Turn around time, and second is the Waiting Time
     * @param fbv Feedback, assumes first value in array is Turn around time, and second is the Waiting Time
     * @param ltr Lottery, assumes first value in array is Turn around time, and second is the Waiting Time
     */
    public void printAverages(double[] fcfs, double[] srt, double[] fbv, double[] ltr)
    {
        System.out.println("\nAlgorithm \tAverage Turnaround Time \tAverage Waiting Time");

        System.out.printf("FCFS\t\t%.2f\t\t\t\t%.2f\n",fcfs[0],fcfs[1]);
        System.out.printf("SRT\t\t%.2f\t\t\t\t%.2f\n",srt[0],srt[1]);
        System.out.printf("FBV\t\t%.2f\t\t\t\t%.2f\n",fbv[0],fbv[1]);
        System.out.printf("LTR\t\t%.2f\t\t\t\t%.2f\n",ltr[0],ltr[1]);


    }

    /**
     * Print the results about the last run values.
     */
    public void printResults()
    {       
        System.out.println("\nProcess \tTurnaround Time \tWaiting Time");
        for (int i = 0; i < processList.size(); i++)
        {
            System.out.print(processList.get(i).getId()+"\t\t");
            System.out.print(processList.get(i).getTurnTime()+"\t\t\t");
            System.out.print(processList.get(i).getWaitTime()+"\n");
        }
    }    
    /**
     * readFile. Reads the file given, creating processes as needed to save details.
     * @param fileNameInput address of the file to be read in.
     */
    public void readFile()
    {
        boolean fileRead = false;
        Scanner sc = new Scanner(System.in);

        Scanner fileReader; //Scanner to read the file.
        File dataSet;// = new File(fileNameInput);

        while(!fileRead)
        {
            System.out.print("Enter filename: ");
            String fileNameInput = sc.nextLine();
            
            dataSet = new File(fileNameInput);
            //Try and open file. If it works, procede.
            try {
                fileReader = new Scanner(dataSet);
                fileRead = true;

                //Progress through each line in the text file
                while(fileReader.hasNextLine()){
                    String line = fileReader.nextLine();
                    
                    //If the line has "EOF" written, stop reading lines.
                    if(line.equals("EOF"))
                    {

                        break;
                    }

                    else if(line.startsWith("DISP"))
                    {
                        disp =Integer.parseInt(line.substring(6));
                    }
                    
                    //If the Line starts with "ID:", create a new process
                    else if(line.startsWith("ID:"))
                    {
                        //Create new proccess
                        Process temp = new Process();


                        temp.setId(line.substring(4));   //Set the id of the proccess to whatever remains of the line after the "ID: "

                        //As we've read in the ID, we shall assume the following lines (until "END") are all part of the process definition.
                        while(fileReader.hasNextLine())
                        {
                            line = fileReader.nextLine();

                            if(line.equals("END"))
                            {
                                break;
                            }
                            
                            else if(line.startsWith("Arrive:"))
                            {   
                                temp.setArrive(Integer.parseInt(line.substring(8))); 
                            }

                            else if(line.startsWith("ExecSize:"))
                            {   
                                
                                temp.setSize(Integer.parseInt(line.substring(10))); 
                            }                        
                            
                            else if(line.startsWith("Tickets:"))
                            {   
                                temp.setTickets(Integer.parseInt(line.substring(9))); 
                            }    

                            else 
                            {
                                //Delete process?
                            }
                        }

                        processList.add(temp);
                    }
                    
                    //If we read the line "BEGINRANDOM", we've started the random numbers section. Until the "ENDRANDOM" line,
                    //we'll just keep reading in each number (and it is assumed each line is a single number) and adding it 
                    //to the random number array.
                    else if(line.equals("BEGINRANDOM"))
                    {
                        while(fileReader.hasNextLine())
                        {
                            line = fileReader.nextLine();

                            if(line.equals("ENDRANDOM"))
                            {
                                break;
                            }
                            else
                            {
                                randomNum.add(Integer.parseInt(line));
                            }
                        }
                    }
                }
                fileReader.close();
            } 
            
            //If the file isn't found, throw a hissy fit.
            catch (FileNotFoundException e) {
                System.out.println("File not found.");
                //e.printStackTrace();  //Optional, shows more data.
            }
        }
        //Close the scanner
        sc.close();
    }    
}