package Test;

import API.*;
import MNP.*;

// 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 MainMenu parent;

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

    private JTable currentJTableUse;
    private JComboBox<String> list;
    private JComboBox<String> requestTypeSelector;

    private JTextArea content;

    private ArrayList<String> tmpStud;

    private int x;

    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);
    }

    /**
     *
     * Récuperer le nombre de membres d'un groupe
     *
     * @param id le groupes
     * @return le nombre de membre
     * */     public int getMemberCount(int id) {
        int j = 0;

        for(int i = 0; i <= this.e.size()-1; i++) {
            if(this.e.get(i).getGroupe() == id) {
                j++;
            }
        } 

        return j; 
    }

    /**
     * Pour créer une JTable
     * @param data Les données
     * @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;
            }
        };
    }

    // TODO: mettre a jour les parametres de la methode la pluplart sont inutiles
    /**
     * Pour afficher une JTable sans listener
     *
     * @param frameTitle Le titre de la fenêtre
     * @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;

        this.parent.updateTable(liste);

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

    // TODO: mettre à jour les paramètres de la méthode la pluplart sont inutisées
    /**
     * Pour afficher une JTable contenant un listener
     *
     * @param frameTitle Le titre de la fenêtre
     * @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;

        this.parent.updateTable(liste);
    }

    /**
     * Pour afficher une modale classique pour plus de libertées (panel a créer au préalable)
     *
     * @param frameTitle Le titre de la fenêtre
     * @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 fenêtre (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();
        this.e = this.db.getEtuList();
        String groupeOption = this.pv.getComboSelection();
        int groupeIndex = 0;
        String text = this.pv.getSearchStud();

        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") ||
                    Objects.equals(command, "sv::GetListFiltered")) {

            if(Objects.equals(command, "pv::GetListFiltered")) {
                groupeIndex = this.pv.getComboSelectionIndex();
            } else {
                groupeIndex = this.sv.getComboSelectionIndex();
            }

            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'élèves 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 saisir 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,
                            "Elève 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(
                    "Déplacer un étudiant",
                    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 étudiant",
                    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) + " est dans le " + this.list.getSelectedItem() + " à présent",
                        "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 être deplacé",
                        "Erreur lors du déplacement",
                        JOptionPane.ERROR_MESSAGE
                );
            }
            //this.currentModal.dispose();
        }

        else if(Objects.equals(command, "sv::GetGrup")) {
            String[][] data = new String[this.g.size()][];

            String[] title = new String[] {
              "ID", "Nom", "Taille"
            };

            for(int i = 0; i <= this.g.size()-1; i++) {
                data[i] = new String[]{
                        String.valueOf(this.g.get(i).getId()),
                        this.g.get(i).getName(),
                        this.getMemberCount(i) + "/" + this.g.get(i).getMax()
                };
            }

            DisplayWithListner(
                    "Liste des groupes",
                    350,
                    400,
                    this.sv.getX(),
                    this.sv.getY(),
                    this.createJTable(data, title)
            );
        }

        else if(Objects.equals(command, "sv::MakeRequest")) {
            JPanel forModal = new JPanel(new GridBagLayout());
            BLayout settings = new BLayout();
            settings.setPositionY(0);
            settings.setPositionX(0);

            /**
             * TODO:
             *         - Demande de type...
             *         - Vers quel groupe
             *         - possible ou nn
             *         - message
             *         - Valider
             * */

            settings.setPositionY(1);
            JLabel requestT =  new JLabel("Dans quel groupe souhaitez-vous aller ?");
            forModal.add(requestT, settings);

            settings.setPositionY(2);
            this.requestTypeSelector = new JComboBox<>();

            for(int i = 0; i <= this.g.size()-1; i++) {
                this.requestTypeSelector.addItem(this.g.get(i).getName());
            }

            forModal.add(this.requestTypeSelector, settings);

            settings.setPositionY(3);
            forModal.add(new JLabel(" "), settings);

            settings.setPositionY(4);
            this.content = new JTextArea();
            this.content.setPreferredSize(new Dimension(450, 250));
            forModal.add(this.content, settings);

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

            settings.setPositionY(6);
            JButton confirmRequ = new JButton("Envoyer");
            confirmRequ.addActionListener(this);
            confirmRequ.setActionCommand("sv::SendRequest");
            forModal.add(confirmRequ, settings);

            DisplayModal(
                    "Veuillez entrer un message...",
                    750,
                    500,
                    1,
                    1,
                    forModal
            );
        }

        else if(Objects.equals(command, "sv::SendRequest")) {
            int groupe = (int) this.requestTypeSelector.getSelectedIndex();
            String message = this.content.getText();
            System.out.println(groupe);

            // Etudiant qui est supposé utiliser cette vue
            Etudiant forTest = new EtudiantNP("Boudjemline", "Bilal", -1);
            int id = 115;
            int x = this.getMemberCount(-1);
            int type;
            int y = this.getMemberCount(groupe);

            if(x > y || x == y) { // Type 1
                type = 1;
            } else { // Type 2
                type = 2;
            }

            if(this.db.insertRow("fi_demandes", new String[] {
                    "id_eleve", "id_groupe", "message", "type"}, new String[] {
                    String.valueOf(id), String.valueOf(groupe), message, String.valueOf(type)
            })) {
                JOptionPane.showMessageDialog(
                        this.pv,
                        "Votre requête a été envoyé avec succes !",
                        "Requête.",
                        JOptionPane.INFORMATION_MESSAGE
                );
            } else {
                JOptionPane.showMessageDialog(
                        this.sv,
                        "Une erreur est survenue lors de l'envoie de votre message...\nVeuillez reesayer plus tard.",
                        "Erreur avec la base de données.",
                        JOptionPane.ERROR_MESSAGE
                );
            }
        }

        else if(Objects.equals(command, "sv::ShowRequest")) {
            JPanel forModal = new JPanel();
            int nbMessage;
            int moi = 115;

            ArrayList<String> idm = this.db.fetchAll("SELECT id FROM fi_demandes WHERE id_eleve = " + moi);
            ArrayList<String> message = this.db.fetchAll("SELECT message FROM fi_demandes WHERE id_eleve = " + moi);
            ArrayList<String> statut = this.db.fetchAll("SELECT statut FROM fi_demandes WHERE id_eleve = " + moi);

            Object[][] data = new Object[idm.size()][];

            String[] title = new String[] {
                    "ID", "Contenu", "Statut"
            };

            for(int i = 0; i <= idm.size()-1; i++) {
                String[] info = {
                    "#" + idm.get(i), message.get(i), statut.get(i)
                };

                data[i] = info;
            }

            Display(
                    "Vos demandes",
                    500,
                    500,
                    1,
                    1,
                    this.createJTable(data, title)
            );
        }
    }

    @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]")) {
                        addMoveStudent(tm, cell, "[DEPLACER]");
                    }

                    if(Objects.equals(value, "[AJOUTER]")) {
                        addMoveStudent(tm, cell, "[AJOUTER]");
                    }
                }
            }
        }
    }


    private void addMoveStudent(TableModel tm, int[] cell, String action){
        String[] stringSetAdd = {
                "Ajouter ",
                "Ajouter",
                "Nouveau groupe de l'élève : "
        };
        String[] stringSetMove = {
                "Deplacer ",
                "Deplacer",
                "Deplacer l'élève : "
        };
        String[] stringSet;

        if (action == "[AJOUTER]"){
            stringSet = stringSetAdd;
        } else {
            stringSet = stringSetMove;
        }

        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(
                stringSet[0] +  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(stringSet[1]);
        moveBtn.setActionCommand("crtll::ActionAddAndMoveGrup");
        moveBtn.addActionListener(this);
        forModal.add(moveBtn, settings);

        DisplayModal(
                stringSet[2]
                        + tm.getValueAt(cell[0], 0) + " " + tm.getValueAt(cell[0], 1),
                500,
                250,
                this.parent.getLocation().x + (this.parent.getSize().width  - 500) / 2,
                this.parent.getLocation().y + (this.parent.getSize().height - 250) / 2,
                forModal
        );
        this.parent.updateTable(this.initTable());
    }

    public JTable initTable() {
        Object[][] data = new Object[this.e.size()][3];
        String[] title = {
                "Nom",
                "Prenom",
                "Groupe",
        };
        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())
            };
            data[i] = info;
        }
        return createJTable(data, title);
    }

    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;
    }
}