package logica.reportes;

import com.thoughtworks.xstream.XStream;
import logica.Search;
import logica.Utilities;
import org.json.XML;
import orm.*;

import javax.xml.transform.TransformerException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;

/**
 * Clase que almacena a los apoderados con mas de un estudiante.
 */
public class ReporteApoderadosMasEstudiantes {
    private HashMap<Apoderado, ArrayList<Estudiante>> apoderadosDuplicados;

    /**
     * Crea el objeto de reporte realizando la query para almacenar los apoderados con mas de un estudiante en un hashmap
     */
    public ReporteApoderadosMasEstudiantes() {
        apoderadosDuplicados = new HashMap<>();
        HashMap<Apoderado, Estudiante> apoderados = new HashMap<>();
        Curso[] cursos = Search.buscarCursos();
        if (cursos != null) {
            for (Curso c : cursos) {
                Estudiante[] estudiantes = Search.buscarEstudiantes(c);
                if (estudiantes != null) {
                    for (Estudiante e : estudiantes) {
                        if (apoderados.containsKey(e.getApoderado_id_fk())) {
                            if (apoderadosDuplicados.containsKey(e.getApoderado_id_fk())) {
                                apoderadosDuplicados.get(e.getApoderado_id_fk()).add(e);
                            } else {
                                ArrayList<Estudiante> temp = new ArrayList<>();
                                temp.add(apoderados.get(e.getApoderado_id_fk()));
                                temp.add(e);
                                apoderadosDuplicados.put(e.getApoderado_id_fk(), temp);
                            }
                        }
                        apoderados.put(e.getApoderado_id_fk(), e);
                    }
                }
            }
        }
    }

    /**
     * Genera los archivos del reporte, xml, json, html, xlsx o docx segun se indique a travez de transformaciones xls
     *
     * @param xslPath La carpeta en la que se encuentran los archivos xsl
     * @param xml     Si se guarda el archivo xml
     * @param json    Si se guarda el archivo json
     * @param html    Si se guarda el archivo html
     * @param xlsx    Si se guarda el archivo xlsx
     * @param docx    Si se guarda el archivo docx
     */
    public HashMap<String, String> generar(File xslPath, boolean xml, boolean json, boolean html, boolean xlsx, boolean docx) {
        HashMap<String, String> reportes = new HashMap<>();
        XStream xstream = new XStream();
        xstream.setMode(XStream.NO_REFERENCES);
        setXStream(xstream);

        String xmlResult = xstream.toXML(this);
        String jsonResult = XML.toJSONObject(xmlResult).toString();

        try {
            PrintWriter outXml = new PrintWriter("files/reportes/reporteApoderadosMasEstudiantes/reporteApoderadosMasEstudiantes.xml");
            outXml.println(xmlResult);
            outXml.close();
            if (json) {
                PrintWriter outJson = new PrintWriter("files/reportes/reporteApoderadosMasEstudiantes/reporteApoderadosMasEstudiantes.json");
                outJson.println(jsonResult);
                outJson.close();
                reportes.put("json", jsonResult);
            }
            if (html) {
                XslTransformer.transform(
                        xslPath.getPath() + "/toHtmlApoderadosMasEstudiantes.xsl",
                        "files/reportes/reporteApoderadosMasEstudiantes/reporteApoderadosMasEstudiantes.xml",
                        "files/reportes/reporteApoderadosMasEstudiantes/reporteApoderadosMasEstudiantes.html"
                );
                reportes.put("html", Utilities.readFile("files/reportes/reporteApoderadosMasEstudiantes/reporteApoderadosMasEstudiantes.html"));
            }
            if (xlsx) {
                XslTransformer.transform(
                        xslPath.getPath() + "/toExcelApoderadosMasEstudiantes.xsl",
                        "files/reportes/reporteApoderadosMasEstudiantes/reporteApoderadosMasEstudiantes.xml",
                        "files/reportes/reporteApoderadosMasEstudiantes/reporteApoderadosMasEstudiantes.xlsx"
                );
                reportes.put("xlsx", Utilities.readFile("files/reportes/reporteApoderadosMasEstudiantes/reporteApoderadosMasEstudiantes.xlsx"));
            }
            if (docx) {
                XslTransformer.transform(
                        xslPath.getPath() + "/toWordApoderadosMasEstudiantes.xsl",
                        "files/reportes/reporteApoderadosMasEstudiantes/reporteApoderadosMasEstudiantes.xml",
                        "files/reportes/reporteApoderadosMasEstudiantes/reporteApoderadosMasEstudiantes.docx"
                );
                reportes.put("docx", Utilities.readFile("files/reportes/reporteApoderadosMasEstudiantes/reporteApoderadosMasEstudiantes.docx"));
            }
            if (!xml) {
                File deleteFile = new File("files/reportes/reporteApoderadosMasEstudiantes/reporteApoderadosMasEstudiantes.xml");
                deleteFile.delete();
            } else {
                reportes.put("xml", xmlResult);
            }
        } catch (FileNotFoundException | TransformerException e) {
            e.printStackTrace();
        }
        return reportes;
    }

    /**
     * Inicia XStream con propiedades deseadas, para no mostrar datos innecesarios de las clases y asignarles alias a las clases para no mostrar las rutas completas de estas.
     *
     * @param xstream Instancia de XStream a modificar.
     */
    public void setXStream(XStream xstream) {
        xstream.alias("Actividad", Actividad.class);
        xstream.alias("Anotacion", Anotacion.class);
        xstream.alias("Apoderado", Apoderado.class);
        xstream.alias("Asignatura", Asignatura.class);
        xstream.alias("Asistencia", Asistencia.class);
        xstream.alias("Colegio", Colegio.class);
        xstream.alias("Curso", Curso.class);
        xstream.alias("Estudiante", Estudiante.class);
        xstream.alias("Nota", Nota.class);
        xstream.alias("Profesor", Profesor.class);

        xstream.omitField(Actividad.class, "id_pk");
        xstream.omitField(Actividad.class, "_ormAdapter");

        xstream.omitField(Anotacion.class, "id_pk");
        xstream.omitField(Anotacion.class, "_ormAdapter");

        xstream.omitField(Apoderado.class, "id_pk");
        xstream.omitField(Apoderado.class, "colegio_id_fk");
        xstream.omitField(Apoderado.class, "ORM_estudiante");
        xstream.omitField(Apoderado.class, "_ormAdapter");
        xstream.omitField(Apoderado.class, "estudiante");

        xstream.omitField(Asignatura.class, "id_pk");
        xstream.omitField(Asignatura.class, "_ormAdapter");
        xstream.omitField(Asignatura.class, "ORM_actividad");
        xstream.omitField(Asignatura.class, "ORM_nota");
        xstream.omitField(Asignatura.class, "actividad");
        xstream.omitField(Asignatura.class, "nota");

        xstream.omitField(Asistencia.class, "id_pk");
        xstream.omitField(Asistencia.class, "_ormAdapter");

        xstream.omitField(Colegio.class, "id_pk");
        xstream.omitField(Colegio.class, "_ormAdapter");
        xstream.omitField(Colegio.class, "ORM_curso");
        xstream.omitField(Colegio.class, "ORM_apoderado");
        xstream.omitField(Colegio.class, "ORM_profesor");
        xstream.omitField(Colegio.class, "curso");
        xstream.omitField(Colegio.class, "apoderado");
        xstream.omitField(Colegio.class, "profesor");

        xstream.omitField(Curso.class, "id_pk");
        xstream.omitField(Curso.class, "_ormAdapter");
        xstream.omitField(Curso.class, "ORM_asignatura");
        xstream.omitField(Curso.class, "ORM_estudiante");
        xstream.omitField(Curso.class, "asignatura");
        xstream.omitField(Curso.class, "estudiante");

        xstream.omitField(Estudiante.class, "id_pk");
        xstream.omitField(Estudiante.class, "_ormAdapter");
        xstream.omitField(Estudiante.class, "ORM_anotacion");
        xstream.omitField(Estudiante.class, "ORM_nota");
        xstream.omitField(Estudiante.class, "ORM_asistencia");
        xstream.omitField(Estudiante.class, "anotacion");
        xstream.omitField(Estudiante.class, "nota");
        xstream.omitField(Estudiante.class, "asistencia");

        xstream.omitField(Nota.class, "id_pk");
        xstream.omitField(Nota.class, "_ormAdapter");

        xstream.omitField(Profesor.class, "id_pk");
        xstream.omitField(Profesor.class, "_ormAdapter");
        xstream.omitField(Profesor.class, "ORM_asignatura");
        xstream.omitField(Profesor.class, "ORM_anotacion");
        xstream.omitField(Profesor.class, "asignatura");
        xstream.omitField(Profesor.class, "anotacion");

    }

}
