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.HashMap;

/**
 * Clase que almancena las planificaciones de los pupilos de un apoderado
 */
public class ReportePlanificaciones {
    private HashMap<Estudiante, HashMap<Asignatura, Actividad[]>> planificaciones;
    private Apoderado apoderado;

    public ReportePlanificaciones(Apoderado apoderado) {
        this.apoderado = apoderado;
        planificaciones = 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 (e.getApoderado_id_fk().equals(apoderado)) {
                            HashMap<Asignatura, Actividad[]> map = new HashMap<>();
                            Asignatura[] asignaturas = Search.buscarAsignaturas(c);
                            if (asignaturas != null) {
                                for (Asignatura asignatura : asignaturas) {
                                    Actividad[] actividades = Search.buscarActividades(asignatura);
                                    map.put(asignatura, actividades);
                                }
                            }
                            planificaciones.put(e, map);
                        }
                    }
                }
            }
        }
    }

    /**
     * Guarda el reporte generado segun lo indicado en los boleanos entregados
     *
     * @param xslPath ruta en la cual se encuentran los xsl para la transformacion
     * @param xml Si se guardara el xml
     * @param json Si se guardara el json
     * @param html Si se guardara el html
     * @param xlsx Si se guardara el xlsx
     * @param docx Si se guardara el docx
     * @return un hashmap con los reportes generados en el
     */
    public HashMap<String, String> generar(File xslPath, boolean xml, boolean json, boolean html, boolean xlsx, boolean docx) {
        HashMap<String, String> reporte = new HashMap<>();

        XStream xstream = new XStream();
        setXStream(xstream);
        xstream.setMode(XStream.NO_REFERENCES);

        String xmlResult = xstream.toXML(this);

        try {
            PrintWriter outXml = new PrintWriter("files/reportes/reportePlanificaciones/" + apoderado.getRut() + "-Planificaciones.xml");
            outXml.println(xmlResult);
            outXml.close();

            if(json){
                PrintWriter outJson = new PrintWriter("files/reportes/reportePlanificaciones/" + apoderado.getRut() + "-Planificaciones.json");
                String jsonResult = XML.toJSONObject(xmlResult).toString();
                outJson.println(jsonResult);
                outJson.close();
                reporte.put("json", Utilities.readFile("files/reportes/reportePlanificaciones/" + apoderado.getRut() + "-Planificaciones.json"));
            }

            if (html) {
                XslTransformer.transform(
                        xslPath.getPath() + "/toHtmlPlanificaciones.xsl",
                        "files/reportes/reportePlanificaciones/" + apoderado.getRut() + "-Planificaciones.xml",
                        "files/reportes/reportePlanificaciones/" + apoderado.getRut() + "-Planificaciones.html"
                );
                reporte.put("html", Utilities.readFile("files/reportes/reportePlanificaciones/" + apoderado.getRut() + "-Planificaciones.html"));
            }
            if (xlsx) {
                XslTransformer.transform(
                        xslPath.getPath() + "/toExcelPlanificaciones.xsl",
                        "files/reportes/reportePlanificaciones/" + apoderado.getRut() + "-Planificaciones.xml",
                        "files/reportes/reportePlanificaciones/" + apoderado.getRut() + "-Planificaciones.xlsx"
                );
                reporte.put("xlsx", Utilities.readFile("files/reportes/reportePlanificaciones/" + apoderado.getRut() + "-Planificaciones.xlsx"));
            }
            if (docx) {
                XslTransformer.transform(
                        xslPath.getPath() + "/toWordPlanificaciones.xsl",
                        "files/reportes/reportePlanificaciones/" + apoderado.getRut() + "-Planificaciones.xml",
                        "files/reportes/reportePlanificaciones/"+ apoderado.getRut() + "-Planificaciones.docx"
                );
                reporte.put("docx", Utilities.readFile("files/reportes/reportePlanificaciones/" + apoderado.getRut() + "-Planificaciones.docx"));
            }
            if(!xml){
                File deleteFile = new File("files/reportes/reportePlanificaciones/" + apoderado.getRut() + "-Planificaciones.xml");
                deleteFile.delete();
            }else{
                reporte.put("xml",xmlResult);
            }
        } catch (FileNotFoundException | TransformerException e) {
            e.printStackTrace();
        }
        return reporte;
    }

    /**
     * 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");

        xstream.omitField(ReportePlanificaciones.class, "apoderado");
    }
}
