package Test;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;

/**
 * La fenêtre principale contenant les vues
 */
public class MainMenu extends JFrame {
    public static final int MENU = 0, ADMIN = 1, PROF = 2, STUDENT = 3;
    private static final int FULL = 4, WINDOW = 5;
    private final static Dimension MINIMUM_SIZE = new Dimension(960, 600);
    private final CardLayout cards = new CardLayout(), adminCards = new CardLayout(), profCards = new CardLayout(),
            studentCards = new CardLayout();
    private final JPanel adminPanel = new JPanel(), profPanel = new JPanel(), studentPanel = new JPanel();
    private final Color adminColor = new Color(255, 2, 2);
    private final Color profColor = new Color(182, 2, 189);
    private final Color studentColor = new Color(53, 242, 242);
    private int screenStatus = WINDOW;
    private int currentView = MENU;
    private JMenuBar menuBar;
    private Controller listener;
    private AdminView av;
    private ProfView pv;
    private StudentView sv;
    private JTable table;
    private int cardIndex = 0;
    private boolean uniqueView = false;
    private String[] viewName = { "Administrateur", "Professeur", "Etudiant" };
    private final CustomJButton[] buttonTab = {
            new CustomJButton(viewName[0]),
            new CustomJButton(viewName[1]),
            new CustomJButton(viewName[2])
    };

    /**
     * Constructeur de base
     * 
     * @param listener controller initialisé dans le main
     */
    public MainMenu(Controller listener) {
        super();
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setExtendedState(MAXIMIZED_BOTH);
        this.setMinimumSize(MINIMUM_SIZE);
        init(listener);
        this.setVisible(true);
    }

    public MainMenu(Controller listener, int selectedView) {
        super();
        this.uniqueView = true;
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setExtendedState(MAXIMIZED_BOTH);
        this.setMinimumSize(MINIMUM_SIZE);

        init(listener);
        initView(selectedView);

        this.setVisible(true);
    }

    /**
     * Construit un objet MainMenu sur la vue sélectionnée et le mode d'affichage
     * choisi
     * 
     * @param listener     controller initialisé dans le main
     * @param selectedView vue à afficher
     * @param screenStyle  disposition d'affichage plein écran ou fenêtré
     */
    public MainMenu(Controller listener, int selectedView, int screenStyle) {
        super();
        this.uniqueView = true;
        this.setDefaultCloseOperation(EXIT_ON_CLOSE);
        this.setExtendedState(MAXIMIZED_BOTH);
        this.setMinimumSize(MINIMUM_SIZE);

        init(listener);
        setScreenStyle(screenStyle);
        initView(selectedView);

        this.setVisible(true);

    }

    /**
     * Initialise les paramètres de la fenêtre
     * 
     * @param listener
     */
    private void init(Controller listener) {
        this.listener = listener;

        this.av = this.listener.getAdminView();
        this.pv = this.listener.getProfView();
        this.sv = this.listener.getStudentView();

        this.table = this.listener.initTable();

        this.setLayout(cards);

        this.add(firstCard());

        this.add(adminPanel);
        this.add(profPanel);
        this.add(studentPanel);

        cards.first(this.getContentPane());
    }

    /**
     * Action réalisée par les boutons du menu principal
     * 
     * @param e
     */
    private void action(ActionEvent e) {
        JButton origin = (JButton) e.getSource();

        if (origin.getText().equals(viewName[0])) {
            initView(ADMIN);
        } else if (origin.getText().equals(viewName[1])) {
            initView(PROF);
        } else {
            initView(STUDENT);
        }
    }

    /**
     * Crée le bar de menu
     */
    private void createJMenuBar() {
        JMenu menu = new JMenu("Menu"), view = new JMenu("Affichage");

        if (!uniqueView) {
            JMenuItem adminMenuItem = new JMenuItem("Vue " + viewName[0]);
            adminMenuItem.addActionListener((event) -> changeView(1));

            JMenuItem profMenuItem = new JMenuItem("Vue " + viewName[1]);
            profMenuItem.addActionListener((event) -> changeView(2));

            JMenuItem studentMenuItem = new JMenuItem("Vue " + viewName[2]);
            studentMenuItem.addActionListener((event) -> changeView(3));

            JMenuItem mainMenuItem = new JMenuItem("Retourner au menu principal");
            mainMenuItem.addActionListener(this::backtoMainMenu);

            menu.add(adminMenuItem);
            menu.add(profMenuItem);
            menu.add(studentMenuItem);
            menu.add(mainMenuItem);
        }

        JMenuItem fullScreenMenuItem = new JMenuItem("Plein écran");
        fullScreenMenuItem.addActionListener(this::setFullScreen);

        JMenuItem notFullScreenMenuItem = new JMenuItem("Fenêtré");
        notFullScreenMenuItem.addActionListener(this::unsetFullScreen);

        JMenuItem quitMenuItem = new JMenuItem("Quitter");
        quitMenuItem.addActionListener((event) -> System.exit(0));

        menu.add(quitMenuItem);

        view.add(fullScreenMenuItem);
        view.add(notFullScreenMenuItem);

        menuBar.add(menu);
        menuBar.add(view);

        this.setJMenuBar(menuBar);
    }

    /**
     * Crée une vue avec le résultat de la base de données à côté
     * 
     * @param sidePanel actions relatives à l'utilisateur
     * @param origin
     * @return panel contenant les boutons et la table
     */
    private JPanel cardWithTable(JPanel sidePanel, String origin) {
        JPanel panel = new JPanel();
        JScrollPane scrollPane = new JScrollPane();

        panel.setLayout(new GridLayout(1, 2));

        if (origin.equals(viewName[0])) {
            sidePanel.setBackground(adminColor);

        } else if (origin.equals(viewName[1])) {
            sidePanel.setBackground(profColor);

        } else {
            sidePanel.setBackground(studentColor);
        }

        panel.add(sidePanel);
        panel.add(this.table);
        panel.add(scrollPane);
        scrollPane.setViewportView(this.table);

        return panel;
    }

    /**
     * Permet de naviguer entre les vues
     * 
     * @param index index de la vue
     */
    private void changeView(int index) {
        table = this.listener.initTable();

        if (index == 1) {
            this.cardIndex = index;
            this.currentView = ADMIN;
            this.setTitle(this.viewName[0]);
            this.adminPanel.setLayout(this.adminCards);
            this.adminPanel.add(cardWithTable(adminView(), viewName[0]));
            this.adminCards.next(this.adminPanel);
            this.menuBar.setBackground(this.adminColor);

        } else if (index == 2) {
            this.cardIndex = index;
            this.currentView = PROF;
            this.setTitle(this.viewName[1]);
            this.profPanel.setLayout(this.profCards);
            this.profPanel.add(cardWithTable(profView(), viewName[1]));
            this.profCards.next(this.profPanel);
            this.menuBar.setBackground(this.profColor);

        } else if (index == 3) {
            this.cardIndex = index;
            this.currentView = STUDENT;
            this.setTitle(this.viewName[2]);
            this.studentPanel.setLayout(this.studentCards);
            this.studentPanel.add(cardWithTable(studentView(), viewName[2]));
            this.studentCards.next(this.studentPanel);
            this.menuBar.setBackground(this.studentColor);
        }

        travelThroughCards(index);
    }

    /**
     * Met à jour la table de cet objet
     * 
     * @param table nouvelle table
     */
    public void updateTable(JTable table) {
        if (cardIndex == 1) {
            this.table = table;
            adminPanel.add(cardWithTable(adminView(), viewName[0]));
            adminCards.next(adminPanel);
        } else if (cardIndex == 2) {
            this.table = table;
            profPanel.add(cardWithTable(profView(), viewName[1]));
            profCards.next(profPanel);
        } else {
            this.table = table;
            studentPanel.add(cardWithTable(studentView(), viewName[2]));
            studentCards.next(studentPanel);
        }
    }

    /**
     * Crée le menu principal
     * 
     * @return panel contenant le menu principal
     */
    private JPanel firstCard() {
        JPanel mainPanel = new JPanel(), centerPanel = new JPanel();
        Dimension buttonDimension = new Dimension(300, 50);

        mainPanel.setLayout(new BorderLayout());
        centerPanel.setLayout(new GridBagLayout());

        Insets insets = new Insets(10, 10, 10, 10);
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = insets;
        gbc.gridwidth = 1;
        gbc.gridx = 0;

        for (int i = 0; i < buttonTab.length; i++) {
            gbc.gridy = i;
            buttonTab[i].setPreferredSize(buttonDimension);
            buttonTab[i].addActionListener(this::action);
            centerPanel.add(buttonTab[i], gbc);
        }

        mainPanel.add(centerPanel, BorderLayout.CENTER);

        return mainPanel;
    }

    /**
     * Initialise la vue sélectionnée
     * 
     * @param index index de la vue choisie
     */
    private void initView(int index) {
        if (menuBar == null) {
            menuBar = new JMenuBar();
            createJMenuBar();
        } else {
            this.setJMenuBar(menuBar);
        }

        if (index == ADMIN) {
            this.setTitle(viewName[0]);
            this.currentView = ADMIN;
            menuBar.setBackground(this.adminColor);
            adminPanel.setLayout(adminCards);
            adminPanel.add(cardWithTable(adminView(), viewName[0]));
            adminCards.next(adminPanel);
            cardIndex = 1;

        } else if (index == PROF) {
            this.setTitle(viewName[1]);
            this.currentView = PROF;
            menuBar.setBackground(this.profColor);
            profPanel.setLayout(profCards);
            profPanel.add(cardWithTable(profView(), viewName[1]));
            profCards.next(profPanel);
            cardIndex = 2;

        } else {
            this.setTitle(viewName[2]);
            this.currentView = STUDENT;
            menuBar.setBackground(this.studentColor);
            studentPanel.setLayout(studentCards);
            studentPanel.add(cardWithTable(studentView(), viewName[2]));
            studentCards.next(studentPanel);
            cardIndex = 3;
        }

        travelThroughCards(cardIndex);
    }

    /**
     * Crée la vue administrateur
     * 
     * @return panel contenant la vue admin
     */
    private JPanel adminView() {
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout());
        mainPanel.add(this.av, BorderLayout.CENTER);
        return mainPanel;
    }

    /**
     * Crée la vue professeur
     * 
     * @return panel contenant la vue professeur
     */
    private JPanel profView() {
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout());
        mainPanel.add(this.pv, BorderLayout.CENTER);
        return mainPanel;
    }

    /**
     * Crée la vue étudiant
     * 
     * @return panel contenant la vue étudiant
     */
    private JPanel studentView() {
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BorderLayout());
        mainPanel.add(this.sv, BorderLayout.CENTER);
        return mainPanel;
    }

    private void travelThroughCards(int index) {
        cards.first(this.getContentPane());

        for (int i = 0; i < index; i++) {
            cards.next(this.getContentPane());
        }
    }

    /**
     * Change le mode d'affichage
     * 
     * @param screenStyle
     */
    private void setScreenStyle(int screenStyle) {
        if (screenStyle == FULL) {
            this.setUndecorated(true);
            this.screenStatus = FULL;

        } else if (screenStyle == WINDOW) {
            this.setUndecorated(false);
            this.screenStatus = WINDOW;
        }
    }

    /**
     * Passe la fenêtre en plein écran
     * 
     * @param e
     */
    private void setFullScreen(ActionEvent e) {
        if (screenStatus != FULL) {
            this.dispose();
            this.listener.setMainMenu(new MainMenu(this.listener, this.currentView, FULL));
        }
    }

    /**
     * Passe la fenêtre en fenêtré
     * 
     * @param e
     */
    private void unsetFullScreen(ActionEvent e) {
        if (screenStatus != WINDOW) {
            this.dispose();
            this.listener.setMainMenu(new MainMenu(this.listener, this.currentView, WINDOW));
        }
    }

    /**
     * Renvoie au menu principal
     * 
     * @param e
     */
    private void backtoMainMenu(ActionEvent e) {
        this.setJMenuBar(null);
        cards.first(this.getContentPane());
    }

}
