package ecoparasite.input;

import java.io.BufferedReader;
import java.io.IOException;
import java.lang.reflect.Array;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

/**
 * Permet de manipuler les fichiers CSV, de les lire et d'en créer des objets RawData pour ces données brutes.
 */
public class InputFactory {

    final private static String DATA_FOLDER = "data/";

    final public static String DATA_MACKEREL = "Campagne/mackerel.97442.csv";
    final public static String DATA_MERLU = "Campagne/merlu2018_75164.csv";
    final public static String DATA_PARASITES_PERU = "Combinés/ParasitesPeru2021.csv";

    /**
     * Construit le chemin vers le fichier de données voulu.
     * @param data De préference via une constante DATA_... de notre classe actuelle.
     * @return Le chemin complet vers le dossier
     */
    public static String buildDataPath( String data ){
        return InputFactory.DATA_FOLDER + data;
    }

    /**
     * Permet de lire les données brutes d'un fichier CSV.
     * @param dataFileName Le chemin du fichier CSV, tiré des constantes DATA_... de notre classe actuelle.
     * @return Une instance de RawData permettant de manipuler les données.
     * @throws IOException
     */
    public static RawData readData( String dataFileName ) throws InputFileException {
        return readData( dataFileName, ";" );
    }

    /**
     * Permet de lire les données brutes d'un fichier CSV.
     * @param dataFileName Le chemin du fichier CSV, tiré des constantes DATA_... de notre classe actuelle.
     * @param separator Le séparateur du fichier CSV, par défaut : ;
     * @return Une instance de RawData permettant de manipuler les données.
     *
     * @throws InputFileException - Une erreur durant la lecture du fichier.
     */
    public static RawData readData( String dataFileName, String separator ) throws InputFileException {

        Path path = Paths.get(InputFactory.buildDataPath(dataFileName));

        BufferedReader reader;
        try {
            reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);
        } catch (IOException e) {
            throw new InputFileException(dataFileName);
        }

        return createRawData(dataFileName, reader, separator);
    }

    /**
     * Fonction appellé par readData, permet de créer l'instance de RawData stockant les données.
     *
     * @param dataFileName Le nom du fichier.
     * @param reader Le BufferedReader des données.
     * @param separator Le séparateur du fichier CSV, par défaut ";"
     * @return L'instance RawData.
     *
     * @throws InputFileException Si une erreur durant la lecture d'une ligne s'est produite.
     */
    private static RawData createRawData( String dataFileName, BufferedReader reader, String separator ) throws InputFileException {

        ArrayList<ArrayList<String>> data = new ArrayList<>();
        String line;

        // Lecture de la première ligne, le nom des colonnes.
        try {
            line = reader.readLine();
        } catch (IOException e) {
            throw new InputFileException( dataFileName );
        }
        String[] rowFields = line.split(separator);

        for( int i = 0; i < rowFields.length; i++ ){
            ArrayList<String> element = new ArrayList<>();
            element.add(rowFields[i]);
            data.add( element );
        }

        // Lecture des autres lignes.
        try {
            while ((line = reader.readLine()) != null) {
                rowFields = line.split(separator, -1);
                for (int i = 0; i < rowFields.length; i++) {
                    ArrayList<String> element = data.get(i);
                    element.add(rowFields[i]);
                }
            }
        } catch (Exception e) {
            throw new InputFileException( dataFileName );
        }

        return new RawData(data);
    }

}
