package cloud.cluster.sim.requestsimulator.logparser;

import cloud.cluster.sim.utilities.SimSettingsExtractor;
import com.sun.istack.internal.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Comparator;

/**
 * Read trace data from files.
 */
public class TraceReader {

    private static final Logger logger = LoggerFactory.getLogger(TraceReader.class);

    private BufferedReader br = null;
    private String[] fileNames = null;
    private int fileNumber = 0;

    /**
     * Stores all file names from which we should read trace data.
     *
     * @throws IOException
     */
    public TraceReader() {
        String pathToTraces = SimSettingsExtractor.getSimulationSettings().getPathToTraces();
        String traceNameRegex = SimSettingsExtractor.getSimulationSettings().getRegexForTracesName();

        try {
            fileNames = Files.walk(Paths.get(pathToTraces))
                     .filter(Files::isRegularFile)                                                                           // only consider fileNames
                     .filter(filePath -> filePath.toString().contains(traceNameRegex))                                       // only fileNames that contain traces in name
                     .sorted(Comparator.naturalOrder())
                     .map(file -> file.toString())
                     .toArray(String[]::new);
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
    }

    /**
     * Provides a buffered reader for the next file.
     *
     * @return null if there are no more file to read, or a file if there are files.
     * @throws FileNotFoundException
     */
    @Nullable
    private BufferedReader readFromNextFile() throws FileNotFoundException {
        if (fileNumber < fileNames.length) {
            br = new BufferedReader(new FileReader(fileNames[fileNumber]));
            fileNumber++;
            return br;
        }
        else {
            return null;
        }
    }

    /**
     * Provide the next line of trace data.
     *
     * @return a line of trace data or null if there are no more lines to read.
     * @throws IOException
     */
    @Nullable
    public String getNextTrace() {
        String traceLine = null;

        try {
            if (br == null) {
                // if there are no more fileNames to read.
                if ((br = readFromNextFile()) == null) {
                    return null;
                }
            }

            boolean checkNextFile = false;

            // search for the next line in the current file or in the next ones
            while (traceLine == null) {
                if (checkNextFile) {
                    // if there are no more fileNames to read.
                    if ((br = readFromNextFile()) == null) {
                        return null;
                    }
                }

                traceLine = br.readLine();
                checkNextFile = true;
            }
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }

        return traceLine;
    }

    public static void main(String[] args) {
        TraceReader tr = new TraceReader();
        String line;
        int counter = 0;

        while ((line = tr.getNextTrace()) != null) {
            counter++;
        }

        System.out.println("Counted " + counter +" lines");
    }
}


@@ -48,16 +48,78 @@
 arser;%0A%0A
+import cloud.cluster.sim.requestsimulator.dto.RequestDetails;%0A
 import c
@@ -1730,534 +1730,8 @@
  %7D%0A%0A
-    /**%0A     * Provides a buffered reader for the next file.%0A     *%0A     * @return null if there are no more file to read, or a file if there are files.%0A     * @throws FileNotFoundException%0A     */%0A    @Nullable%0A    private BufferedReader readFromNextFile() throws FileNotFoundException %7B%0A        if (fileNumber %3C fileNames.length) %7B%0A            br = new BufferedReader(new FileReader(fileNames%5BfileNumber%5D));%0A            fileNumber++;%0A            return br;%0A        %7D%0A        else %7B%0A            return null;%0A        %7D%0A    %7D%0A%0A
     
@@ -2812,16 +2812,17 @@
  return 
+ 
 traceLin
@@ -2827,24 +2827,551 @@
 ine;%0A    %7D%0A%0A
+    /**%0A     * Provides a buffered reader for the next file.%0A     *%0A     * @return null if there are no more file to read, or a file if there are files.%0A     * @throws FileNotFoundException%0A     */%0A    @Nullable%0A    private BufferedReader readFromNextFile() throws FileNotFoundException %7B%0A        if (fileNumber %3C fileNames.length) %7B%0A            br = new BufferedReader(new FileReader(fileNames%5BfileNumber%5D));%0A            fileNumber++;%0A            return br;%0A        %7D%0A        else %7B%0A            return null;%0A        %7D%0A    %7D%0A%0A%0A
     public s
@@ -3490,24 +3490,69 @@
 unter = 0;%0A%0A
+        long startTime = System.nanoTime();%0A%0A
         whil
@@ -3618,32 +3618,226 @@
 r++;%0A        %7D%0A%0A
+        long endTime = System.nanoTime();%0A        long executionTime = (endTime - startTime) / 1000000000;%0A        logger.info(%22Time spend executing:           %22 + executionTime + %22 seconds%22);%0A%0A
         System.o

Return traces in string format from trace reader.