package logica;

import org.apache.commons.lang3.RandomUtils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Stream;

/**
 * Clase con metodos utiles para distintas partes del programa
 * Como la creacion y validacion de ruts con codigo verificador con modulo 11
 * y la generacion de nombres a partir de un archivo con nombre y otro con archivos
 */
public class Utilities {

    /**
     * Valida rut comprobando el digito verificador
     *
     * @param vrut         Rut a comprobar
     * @param vverificador Supuesto digito verificador del rut
     * @return True si es que el digito verificador es correcto y false si no lo es
     */
    public static boolean validarRut(String vrut, String vverificador) {
        boolean flag;
        String rut = vrut.trim();

        String posibleVerificador = vverificador.trim();
        int cantidad = rut.length();
        int factor = 2;
        int suma = 0;
        String verificador;

        for (int i = cantidad; i > 0; i--) {
            if (factor > 7) {
                factor = 2;
            }
            suma += (Integer.parseInt(rut.substring((i - 1), i))) * factor;
            factor++;

        }
        verificador = String.valueOf(11 - suma % 11);
        flag = verificador.equals(posibleVerificador) || (verificador.equals("10")) && (posibleVerificador.toLowerCase().equals("k")) || (verificador.equals("11") && posibleVerificador.equals("0"));
        return flag;
    }

    /**
     * Genera un rut aleatorio entre 10 millones y 21 millones con digito verificador
     *
     * @return rut y su digito verificador segun modulo 11
     */
    public static String getRandomRut() {
        int randomNum = new Random().nextInt((21000000 - 10000000) + 1) + 10000000;
        String rut = String.valueOf(randomNum);
        int cantidad = rut.length();
        int factor = 2;
        int suma = 0;
        String verificador;
        for (int i = cantidad; i > 0; i--) {
            if (factor > 7) {
                factor = 2;
            }
            suma += (Integer.parseInt(rut.substring((i - 1), i))) * factor;
            factor++;

        }
        verificador = String.valueOf(11 - suma % 11);
        if (verificador.equals("11")) {
            verificador = "0";
        } else if (verificador.equals("10")) {
            verificador = "K";
        }
        return rut + verificador;
    }

    /**
     * Genera un nombre aleatorio tomando un nombre y un apellidos de los archivos y juntandolos en un solo string
     *
     * @return Nombre aleatorio
     */
    public static String getRandomName() {
        ArrayList<String> firstNames = new ArrayList<>();
        try (BufferedReader br = new BufferedReader(new FileReader("files/nombre.txt"))) {
            String line = br.readLine();
            while (line != null) {
                line = br.readLine();
                if (line != null) {
                    firstNames.add(line);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        ArrayList<String> lastNames = new ArrayList<>();
        try (BufferedReader br = new BufferedReader(new FileReader("files/apellidos.txt"))) {
            String line = br.readLine();
            while (line != null) {
                line = br.readLine();
                if (line != null) {
                    lastNames.add(line);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        int fnRandom = ThreadLocalRandom.current().nextInt(0, firstNames.size());
        int lnRandom = ThreadLocalRandom.current().nextInt(0, lastNames.size());
        return firstNames.get(fnRandom) + " " + lastNames.get(lnRandom);

    }

    /**
     * Metodo que calcula una nota
     * @param puntajeTotal puntaje total de la evaluacion
     * @param puntajeObtenido puntaje obtenido del estudiante
     * @return Nota en un double, con solo un decimal
     */
    public static double calcularNota(double puntajeTotal, double puntajeObtenido) {
        return Math.floor((((puntajeObtenido / puntajeTotal) * 6) + 1)*10d)/10d;
    }

    /**
     * Calcula el promedio de un array de doubles
     * @param notas array de notas a ser promediadas
     * @return la nota promediada con solo 1 decimal
     */
    public static double calcularPromedio(double[] notas){
        double sum = 0;
        for (double nota : notas) {
            sum+=nota;
        }
        return Math.floor((sum/notas.length)*10d)/10d;
    }

    /**
     * Genera una fecha aleatoria
     *
     * @return Una fecha aleatoria entre 1/1/2017 y el 31/12/2017
     */
    public static Date getRandomDate() {
        GregorianCalendar gc = new GregorianCalendar();

        int year = 2017;

        gc.set(gc.YEAR, year);

        int dayOfYear = RandomUtils.nextInt(1, gc.getActualMaximum(gc.DAY_OF_YEAR));

        gc.set(gc.DAY_OF_YEAR, dayOfYear);
        return gc.getTime();
    }

    /**
     * Lee el contenido de un archivo y lo entrega como string
     * @param filePath Ruta del archivo
     * @return El contenido del archivo
     */
    public static String readFile(String filePath){
        StringBuilder builder = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {

            String line;

            while ((line = br.readLine()) != null) {
                builder.append(line);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        return builder.toString();
    }

}
