package Test;

import API.Etudiant;
import API.Groupe;

// TODO: Trier ca pour faire un import par package utilises (j'ai eu la flemme de le faire)
import javax.swing.*;
import java.awt.*;

import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableModel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Objects;

public class Controller implements ActionListener, ListSelectionListener {
    private final BDatabase db;

    private ProfView pv;
    private AdminView av;
    private StudentView sv;
    private BFrame currentModal;
    private JFrame parent;

    private ArrayList<Etudiant> e;
    private ArrayList<Groupe> g;

    private JTable currentJTableUse;
    private JComboBox<String> list;

    private ArrayList<String> tmpStud;

    public Controller(BDatabase db) {
        this.db = db;
        this.e = this.db.getEtuList();
        this.g = this.db.getGroupeList();

        this.sv = new StudentView(this.e, this.g, this);
        this.pv = new ProfView(this.e, this.g, this);
        this.av = new AdminView(this.e, this.g, this);
        this.parent = new MainMenu(this);
    }

    /**
     * Pour creer une JTable
     * @param data Les donnees
     * @param title Les titres
     * */
    private JTable createJTable(Object[][] data, String[] title) {
        return new JTable(data, title) {
            public boolean editCellAt(int row, int column, java.util.EventObject e) {
                return false;
            }
        };
    }

    /**
     * Pour afficher une JTable sans listener
     *
     * @param frameTitle Le titre de la fenetre
     * @param size_x Taille en x
     * @param size_y Taille en y
     * @param loca_x Localisation en x
     * @param loca_y Localisation en y
     * @param liste La JTable
     * */
    private void Display(String frameTitle, int size_x, int size_y, int loca_x, int loca_y, JTable liste) {
        JPanel forModal = new JPanel();

        ListSelectionModel lsm = liste.getSelectionModel();
        liste.getTableHeader().setReorderingAllowed(false);
        liste.setFillsViewportHeight(true);

        this.currentJTableUse = liste;

        forModal.add(liste);

        BFrame frame = new BFrame(frameTitle, loca_x, loca_y, size_x, size_y, this.parent, forModal);
    }

    /**
     * Pour afficher une JTable contenant un listener
     *
     * @param frameTitle Le titre de la fenetre
     * @param size_x Taille en x
     * @param size_y Taille en y
     * @param loca_x Localisation en x
     * @param loca_y Localisation en y
     * @param liste La JTable
     * */
    private void DisplayWithListner(String frameTitle, int size_x, int size_y, int loca_x, int loca_y, JTable liste) {
        JPanel forModal = new JPanel();

        ListSelectionModel lsm = liste.getSelectionModel();
        lsm.addListSelectionListener(this);
        liste.getTableHeader().setReorderingAllowed(false);
        liste.setFillsViewportHeight(true);

        this.currentJTableUse = liste;

        forModal.add(liste);

        BFrame frame = new BFrame(frameTitle, loca_x, loca_y, size_x, size_y, this.parent, forModal);
    }

    /**
     * Pour afficher une modale classique pour plus de liberte (panel a creer au prealable)
     *
     * @param frameTitle Le titre de la fenetre
     * @param size_x Taille en x
     * @param size_y Taille en y
     * @param loca_x Localisation en x
     * @param loca_y Localisation en y
     * @param forModal Le panel a mettre dans la fenetre (libre)
     * */
    private void DisplayModal(String frameTitle, int size_x, int size_y, int loca_x, int loca_y, JPanel forModal) {
        this.currentModal = new BFrame(frameTitle, loca_x, loca_y, size_x, size_y, this.parent, forModal);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();

        String groupeOption = this.pv.getComboSelection();
        int groupeIndex = this.pv.getComboSelectionIndex();
        String text = this.pv.getSearchStud();

        this.e = this.db.getEtuList();

        if(Objects.equals(command, "pv::GetStudList")) {
            String[][] data = new String[this.e.size()][2];

            String[] titre = {
                    "Nom",
                    "Prenom",
                    "Groupe"
            };

            for(int i = 0; i <= this.e.size()-1; i++) {
                String[] info = {
                        this.e.get(i).getNom(),
                        this.e.get(i).getPrenom(),
                        String.valueOf(this.e.get(i).getGroupe())
                };

                data[i] = info;
            }

            Display(
                    "Liste des etudiants",
                    350,
                    400,
                    this.pv.getX(),
                    this.pv.getY(),
                    this.createJTable(data, titre)
            );
        }

        else if(Objects.equals(command, "pv::GetListFiltered")) {
            String[][] data = new String[this.e.size()][1];

            String[] titre = {
                    "Nom",
                    "Prenom"
            };

            int i, j;

            for(i = 0, j = 0; i <= this.e.size()-1; i++) {
                if(this.e.get(i).getGroupe() == groupeIndex) {
                    String[] info = {
                            this.e.get(i).getNom(),
                            this.e.get(i).getPrenom()
                    };

                    data[j] = info;
                    j++;
                }
            }

            String[][] data_final = new String[j][1];
            for(int x = 0; x <= j-1; x++) {
                data_final[x] = data[x];
            }

            Display(
                    "Liste d'eleve du " + groupeOption,
                    350,
                    400,
                    this.pv.getX(),
                    this.pv.getY(),
                    this.createJTable(data_final, titre)
            );
        }

        else if(Objects.equals(command, "pv::SearchStudentPer3Letters")) {
            if(text.length() < 3 || text == null) {
                JOptionPane.showMessageDialog(
                        this.pv,
                        "Veuillez ecrire 3 lettres",
                        "Erreur.",
                        JOptionPane.ERROR_MESSAGE
                );
            } else {
                char[] beg = text.toCharArray();

                ArrayList<String> filtreEleveNom = db.fetchAll("SELECT nom FROM fi_eleves WHERE nom LIKE '" + beg[0] + beg[1] + beg[2] + "%'");
                ArrayList<String> filtreElevePrenom = db.fetchAll("SELECT prenom FROM fi_eleves WHERE nom LIKE '" + beg[0] + beg[1] + beg[2] + "%'");
                ArrayList<String> filtreEleveGroupe = db.fetchAll("SELECT groupe FROM fi_eleves WHERE nom LIKE '" + beg[0] + beg[1] + beg[2] + "%'");

                System.out.println(filtreEleveGroupe.size() + filtreElevePrenom.size() + filtreEleveGroupe.size());

                if(filtreEleveGroupe.size() == 0 || filtreEleveNom.size() == 0 || filtreElevePrenom.size() == 0) {
                    JOptionPane.showMessageDialog(
                            this.pv,
                            "Eleve introuvable !",
                            "Erreur.",
                            JOptionPane.ERROR_MESSAGE
                    );
                } else {
                    String[] titre = {
                            "Nom",
                            "Prenom",
                            "Groupe"
                    };

                    String[][] data = new String[filtreEleveNom.size()][2];

                    for(int i = 0; i <= filtreEleveNom.size()-1; i++){
                        data[i] = new String[]{
                                filtreEleveNom.get(i),
                                filtreElevePrenom.get(i),
                                String.valueOf(filtreEleveGroupe.get(i))
                        };
                    }

                    Display(
                            "Recherche",
                            350,
                            400,
                            this.pv.getX(),
                            this.pv.getY(),
                            this.createJTable(data, titre)
                    );
                }
            }
        }

        else if(Objects.equals(command, "av::MoveStudGrup")) {
            Object[][] data = new Object[this.e.size()][3];

            String[] titre = {
                    "Nom",
                    "Prenom",
                    "Groupe",
                    "Action"
            };

            for(int i = 0; i <= this.e.size()-1; i++) {
                Object[] info = {
                        this.e.get(i).getNom(),
                        this.e.get(i).getPrenom(),
                        String.valueOf(this.e.get(i).getGroupe()),
                        "[DEPLACER]"
                };

                data[i] = info;
            }

            DisplayWithListner(
                    "Deplacer un etudiant",
                    350,
                    400,
                    this.av.getX(),
                    this.av.getY(),
                    this.createJTable(data, titre)
            );
        }

        else if(Objects.equals(command, "av::AddStudGrup")) {
            ArrayList<ArrayList<String>> data = new ArrayList<>();

            String[] titre = {
                    "Nom",
                    "Prenom",
                    "Groupe",
                    "Action"
            };

            int i, j;

            for(i = 0; i <= this.e.size()-1; i++) {
                if(this.e.get(i).getGroupe() == -1) {
                    ArrayList<String> info = new ArrayList<>();
                    info.add(this.e.get(i).getNom());
                    info.add(this.e.get(i).getNom());
                    info.add(String.valueOf(this.e.get(i).getGroupe()));
                    info.add("[AJOUTER]");

                    data.add(info);
                }
            }

            String[][] stringArray = data.stream().map(u -> u.toArray(new String[0])).toArray(String[][]::new);

            DisplayWithListner(
                    "Attribuer un groupe a un etudiant",
                    350,
                    400,
                    this.av.getX(),
                    this.av.getY(),
                    this.createJTable(stringArray, titre)
            );
        }

        else if(Objects.equals(command, "crtll::ActionAddAndMoveGrup")) {
            this.tmpStud.add(String.valueOf(this.list.getSelectedIndex()));

            String query =
                    "UPDATE fi_eleves SET groupe=" + this.tmpStud.get(2) +
                            " WHERE nom='" + this.tmpStud.get(0) +
                            "' AND prenom='" + this.tmpStud.get(1) + "'"
                    ;

            System.out.println(query);

            if(db.updateRow(query)) {
                JOptionPane.showMessageDialog(
                        this.currentModal,
                        this.tmpStud.get(0) + " " + this.tmpStud.get(1) + " a bien ete deplace dans le " + this.list.getSelectedItem(),
                        "Deplacement effectue",
                        JOptionPane.INFORMATION_MESSAGE
                );

                this.e = this.db.getEtuList();

                System.out.println("[+] Modification de " + this.tmpStud.get(1) + " " + this.tmpStud.get(0) + " effectue");
            } else {
                JOptionPane.showMessageDialog(
                        this.currentModal,
                        this.tmpStud.get(0) + " " + this.tmpStud.get(1) + " n'a pas pu etre deplace",
                        "Erreur lors du deplacement",
                        JOptionPane.ERROR_MESSAGE
                );
            }
        }
    }

    @Override
    public void valueChanged(ListSelectionEvent e) {
        if(!e.getValueIsAdjusting()) {
            int[] cell = this.currentJTableUse.getSelectedRows();
            int collumnCount = this.currentJTableUse.getColumnCount();
            Object value;

            if(cell.length > 0) {
                for(int i = 0; i < collumnCount; i++) {
                    TableModel tm = this.currentJTableUse.getModel();
                    value = tm.getValueAt(cell[0], i);

                    if(Objects.equals(value, "[DEPLACER]")) {
                        JPanel forModal = new JPanel(new GridBagLayout());
                        BLayout settings = new BLayout();

                        this.tmpStud = new ArrayList<>();
                        this.tmpStud.add((String) tm.getValueAt(cell[0], 0));
                        this.tmpStud.add((String) tm.getValueAt(cell[0], 1));

                        settings.setPositionX(0);
                        settings.setPositionY(0);
                        JLabel intro = new JLabel(
                                "Deplacer " +  tm.getValueAt(cell[0], 0) + " " +
                                        tm.getValueAt(cell[0], 1) +
                                " dans le groupe : "
                        );
                        forModal.add(intro, settings);

                        settings.setPositionX(1);
                        settings.setPositionY(0);
                        forModal.add(new JLabel(" "), settings);

                        settings.setPositionX(2);
                        settings.setPositionY(0);
                        forModal.add(new JLabel(" "), settings);

                        settings.setPositionX(3);
                        settings.setPositionY(0);

                        this.list = new JComboBox<>();

                        for(Groupe groupe : this.g) {
                            this.list.addItem(groupe.getName());
                        }

                        forModal.add(list, settings);

                        settings.setPositionX(4);
                        settings.setPositionY(0);
                        forModal.add(new JLabel(" "), settings);

                        settings.setPositionX(5);
                        settings.setPositionY(0);
                        forModal.add(new JLabel(" "), settings);

                        settings.setPositionX(6);
                        settings.setPositionY(0);
                        JButton moveBtn = new JButton("Deplacer");
                        moveBtn.setActionCommand("crtll::ActionAddAndMoveGrup");
                        moveBtn.addActionListener(this);
                        forModal.add(moveBtn, settings);

                        DisplayModal(
                                "Deplacer l'eleve : "
                                        + tm.getValueAt(cell[0], 0) + " " + tm.getValueAt(cell[0], 1),
                                500,
                                250,
                                this.av.getX(),
                                this.av.getY(),
                                forModal
                        );
                    }

                    if(Objects.equals(value, "[AJOUTER]")) {
                        System.out.println("Ajout");
                    }
                }
            }
        }
    }

    public ProfView getProfView() {
        return this.pv;
    }

    public StudentView getStudentView() {
        return this.sv;
    }

    public AdminView getAdminView() {
        return this.av;
    }


    public ArrayList<Etudiant> getEtudiants () {
        return this.e;
    }


    public ArrayList<Groupe> getGroupes() {
        return this.g;
    }
}
