package fr.iutfbleau.projetAgile.Puissance4.View;

import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.colorchooser.AbstractColorChooserPanel;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Dimension;
import java.awt.Insets;
import java.awt.Frame;


import fr.iutfbleau.projetAgile.Puissance4.Controller.ColorActionListener;
import fr.iutfbleau.projetAgile.Puissance4.Controller.ColorChooserListener;
import fr.iutfbleau.projetAgile.Puissance4.Utils.Constants;

/**
 * JDialog personnalisé permettant de choisir un nom et une couleur pour le puissance 4
 */
public class ColorChooserDialog extends JDialog{

    private JTextField field1;
    private JTextField field2;
    private JTextField field3;
    private int playerNumber;
    private boolean confirm = false;

    /**
     * Crée une fenêtre modale avec pour nom "Choisissez vos noms et couleurs"
     * @param owner la {@code Frame} depuis laquelle la fenetre modale est affichée
     * @param modal specifie si la fenêtre modale bloque les interactions avec les fenêtres mères
     * @param playerNumber Nombre de joueurs
     * @see javax.swing.JDialog#JDialog(Frame, boolean)
     */
    public ColorChooserDialog(Frame owner, boolean modal, int playerNumber) {
        super(owner, "Choisissez vos noms et couleurs",modal);
        this.playerNumber = playerNumber;
        this.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();

        int length = 12;
        JColorChooser playerOneChooser = new JColorChooser(Constants.PLAYER_ONE_COLOR);
        JColorChooser playerTwoChooser = new JColorChooser(Constants.PLAYER_TWO_COLOR);
        JColorChooser playerThreeChooser = new JColorChooser(Constants.PLAYER_THREE_COLOR);
        AbstractColorChooserPanel[] panelsP1 = playerOneChooser.getChooserPanels();
        AbstractColorChooserPanel[] panelsP2 = playerTwoChooser.getChooserPanels();
        AbstractColorChooserPanel[] panelsP3 = playerThreeChooser.getChooserPanels();
        
        UIManager.put("ColorChooser.swatchesSwatchSize", new Dimension(length, length));
        UIManager.put("ColorChooser.swatchesRecentSwatchSize", new Dimension(length, length));
        

        for(int i = 1; i < panelsP1.length; i++) {
             playerOneChooser.removeChooserPanel(panelsP1[i]);
             playerTwoChooser.removeChooserPanel(panelsP2[i]);
             playerThreeChooser.removeChooserPanel(panelsP3[i]);
        }

        JButton confirmButton = new JButton("Confirmer");
        confirmButton.setActionCommand(Constants.CONFIRM);
        JButton denyButton = new JButton("Annuler");
        denyButton.setActionCommand(Constants.DENY);

        JPanel panelButton = new JPanel();
        panelButton.add(confirmButton);
        panelButton.add(denyButton);

        Pion pionP1 = new Pion(Constants.PLAYER_ONE);
        Pion pionP2 = new Pion(Constants.PLAYER_TWO);
        Pion pionP3 = new Pion(Constants.PLAYER_THREE);
        ColorActionListener cl = new ColorActionListener(this);
        confirmButton.addActionListener(cl);
        denyButton.addActionListener(cl);

        pionP1.setPreferredSize(new Dimension(50,50));
        pionP2.setPreferredSize(new Dimension(50,50));
        pionP3.setPreferredSize(new Dimension(50,50));
            
        JPanel panelPionP1 = new JPanel();
        JPanel panelPionP2 = new JPanel();
        JPanel panelPionP3 = new JPanel();

        panelPionP1.add(pionP1);
        panelPionP1.setBackground(Constants.BACKGROUND_COLOR);
        panelPionP2.add(pionP2);
        panelPionP2.setBackground(Constants.BACKGROUND_COLOR);
        panelPionP3.add(pionP3);
        panelPionP3.setBackground(Constants.BACKGROUND_COLOR);

        playerOneChooser.setPreviewPanel(panelPionP1);
        playerTwoChooser.setPreviewPanel(panelPionP2);
        playerThreeChooser.setPreviewPanel(panelPionP3);

        playerOneChooser.getSelectionModel().addChangeListener(new ColorChooserListener(pionP1, Constants.PLAYER_ONE));

        playerTwoChooser.getSelectionModel().addChangeListener(new ColorChooserListener(pionP2, Constants.PLAYER_TWO));

        playerThreeChooser.getSelectionModel().addChangeListener(new ColorChooserListener(pionP3, Constants.PLAYER_THREE));


        JPanel panelP1 = new JPanel(new GridBagLayout());
        JPanel panelP2 = new JPanel(new GridBagLayout());
        JPanel panelP3 = new JPanel(new GridBagLayout());
        JLabel labelP1 = new JLabel("Nom et couleur du joueur 1");
        JLabel labelP2 = new JLabel("Nom et couleur du joueur 2");
        JLabel labelP3 = new JLabel("Nom et couleur du joueur 2");
        this.field1 = new JTextField("Joueur 1");
        this.field2 = new JTextField("Joueur 2");
        this.field3 = new JTextField("Joueur 3");

        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.anchor = GridBagConstraints.NORTH;
        gbc.gridwidth = 1;
        gbc.gridheight = 1;
        gbc.weightx = 1;
        gbc.weighty = 0;
        gbc.insets = new Insets(0, 0, 0, 0);
        panelP1.add(labelP1, gbc);

        gbc.gridx = 0;
        gbc.gridy = 1;
        panelP1.add(field1, gbc);

        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.weighty = 0.5;
        panelP1.add(playerOneChooser, gbc);

        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weighty = 0;
        panelP2.add(labelP2, gbc);

        gbc.gridx = 0;
        gbc.gridy = 1;
        panelP2.add(field2, gbc);

        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.weighty = 0.5;
        panelP2.add(playerTwoChooser, gbc);

        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.insets = new Insets(5, 5, 5, 5);
        this.add(panelP1,gbc);
        gbc.gridx = 1;
        gbc.gridy = 0;
        this.add(panelP2,gbc);

        if(playerNumber == 3) {
            gbc.gridx = 0;
            gbc.gridy = 0;
            gbc.weighty = 0;
            panelP3.add(labelP3, gbc);

            gbc.gridx = 0;
            gbc.gridy = 1;
            panelP3.add(field3, gbc);

            gbc.gridx = 0;
            gbc.gridy = 2;
            gbc.weighty = 0.5;
            panelP3.add(playerThreeChooser, gbc);

            gbc.gridx = 0;
            gbc.gridy = 1;
            gbc.gridwidth = 2;
            gbc.insets = new Insets(5, 5, 5, 5);
            this.add(panelP3,gbc);
        }

        gbc.gridx = 1;
        if(playerNumber == 3)
            gbc.gridy = 2;
        else
            gbc.gridy = 1;
        gbc.weighty = 0;
        gbc.fill = GridBagConstraints.NONE;
        gbc.anchor = GridBagConstraints.EAST;
        this.add(panelButton,gbc);

        this.pack();
        this.setResizable(false);
        this.setLocationRelativeTo(owner);
        this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
    }

    /**
     * Vérifie si les couleurs choisies ne sont vont pas être confondues
     * @return true si les couleurs choisies ne sont pas trop similaires renvoie true, sinon false
     * @see <a href="https://en.wikipedia.org/wiki/Color_difference">Wikipedia</a>
     */
    public boolean isColorValid() {
        double distanceBetweenP1AndP2 = Math.sqrt(Math.pow(Constants.PLAYER_TWO_COLOR.getRed() - Constants.PLAYER_ONE_COLOR.getRed(), 2) + Math.pow(Constants.PLAYER_TWO_COLOR.getGreen() - Constants.PLAYER_ONE_COLOR.getGreen(), 2) + Math.pow(Constants.PLAYER_TWO_COLOR.getBlue() - Constants.PLAYER_ONE_COLOR.getBlue(), 2));
        double distanceBetweenP1AndP3 = Math.sqrt(Math.pow(Constants.PLAYER_TWO_COLOR.getRed() - Constants.PLAYER_THREE_COLOR.getRed(), 2) + Math.pow(Constants.PLAYER_TWO_COLOR.getGreen() - Constants.PLAYER_THREE_COLOR.getGreen(), 2) + Math.pow(Constants.PLAYER_TWO_COLOR.getBlue() - Constants.PLAYER_THREE_COLOR.getBlue(), 2));
        double distanceBetweenP2AndP3 = Math.sqrt(Math.pow(Constants.PLAYER_TWO_COLOR.getRed() - Constants.PLAYER_THREE_COLOR.getRed(), 2) + Math.pow(Constants.PLAYER_TWO_COLOR.getGreen() - Constants.PLAYER_THREE_COLOR.getGreen(), 2) + Math.pow(Constants.PLAYER_TWO_COLOR.getBlue() - Constants.PLAYER_THREE_COLOR.getBlue(), 2));
        double distanceBetweenP1AndEmpty = Math.sqrt(Math.pow(Constants.EMPTY_COLOR.getRed() - Constants.PLAYER_ONE_COLOR.getRed(), 2) + Math.pow(Constants.EMPTY_COLOR.getGreen() - Constants.PLAYER_ONE_COLOR.getGreen(), 2) + Math.pow(Constants.EMPTY_COLOR.getBlue() - Constants.PLAYER_ONE_COLOR.getBlue(), 2));
        double distanceBetweenP2AndEmpty = Math.sqrt(Math.pow(Constants.EMPTY_COLOR.getRed() - Constants.PLAYER_TWO_COLOR.getRed(), 2) + Math.pow(Constants.EMPTY_COLOR.getGreen() - Constants.PLAYER_TWO_COLOR.getGreen(), 2) + Math.pow(Constants.EMPTY_COLOR.getBlue() - Constants.PLAYER_TWO_COLOR.getBlue(), 2));
        double distanceBetweenP3AndEmpty = Math.sqrt(Math.pow(Constants.EMPTY_COLOR.getRed() - Constants.PLAYER_THREE_COLOR.getRed(), 2) + Math.pow(Constants.EMPTY_COLOR.getGreen() - Constants.PLAYER_THREE_COLOR.getGreen(), 2) + Math.pow(Constants.EMPTY_COLOR.getBlue() - Constants.PLAYER_THREE_COLOR.getBlue(), 2));
        if(distanceBetweenP1AndP2 < 150f) {
            JOptionPane.showMessageDialog(this,"Les deux couleurs sont trop proches (1,2)","Erreur ", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        if(playerNumber == 3 && distanceBetweenP1AndP3 < 150f) {
            JOptionPane.showMessageDialog(this,"Les deux couleurs sont trop proches (1,3)","Erreur ", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        if(playerNumber == 3 && distanceBetweenP2AndP3 < 150f) {
            JOptionPane.showMessageDialog(this,"Les deux couleurs sont trop proches (2,3)","Erreur ", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        else if(distanceBetweenP1AndEmpty < 150f) {
            JOptionPane.showMessageDialog(this,"La couleur du joueur 1 est trop sombre","Erreur ", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        else if(distanceBetweenP2AndEmpty < 150f) {
            JOptionPane.showMessageDialog(this,"La couleur du joueur 2 est trop sombre","Erreur ", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        else if(playerNumber == 3 && distanceBetweenP3AndEmpty < 150f) {
            JOptionPane.showMessageDialog(this,"La couleur du joueur 3 est trop sombre","Erreur ", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        return true;
    }

    /**
     * Vérifie si les noms sont valides, c'est à dire qu'ils ne sont pas vides, ni identiques
     * @return true si les noms sont valides, false sinon.
    */
    public boolean isNameValid() {
        String J1 = null;
        String J2 = null;
        String J3 = null;
        J1 = field1.getText();
        J2 = field2.getText();
        J3 = field3.getText();
        if(J1.length() > 10) {
            J1 = J1.substring(0, 9);
            this.field1.setText(J1);
        }
        if(J2.length() > 10) {
            J2 = J2.substring(0, 9);
            this.field2.setText(J2);
        } 
        if(J3.length() > 10) {
            J3 = J3.substring(0, 9);
            this.field3.setText(J3);
        }   
        if(J1.isEmpty() || J2.isEmpty() || J3.isEmpty()) {
            JOptionPane.showMessageDialog(this,"Un des noms est vides","Erreur ", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        else if(J1.compareTo(J2) == 0) {
            JOptionPane.showMessageDialog(this,"Les deux noms sont identiques (1,2)","Erreur ", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        else if(J1.compareTo(J3) == 0) {
            JOptionPane.showMessageDialog(this,"Les deux noms sont identiques (1,3)","Erreur ", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        else if(J2.compareTo(J3) == 0) {
            JOptionPane.showMessageDialog(this,"Les deux noms sont identiques (2,3)","Erreur ", JOptionPane.ERROR_MESSAGE);
            return false;
        }
        return true;
    }
    
    /**
     * Permet de récupérer le nom inscrit pour le joueur 1
     * @return un {@code String} correspondant au nom du joueur 1
    */
    public String getPlayerOneName() {
        return this.field1.getText();
    }

    
    /**
     * Permet de récupérer le nom inscrit pour le joueur 2
     * @return un {@code String} correspondant au nom du joueur 2
    */
    public String getPlayerTwoName() {
        return this.field2.getText();
    }

    /**
     * Permet de récupérer le nom inscrit pour le joueur 3
     * @return un {@code String} correspondant au nom du joueur 3
    */
    public String getPlayerThreeName() {
        return this.field3.getText();
    }

    
    /**
     * Permet de confirmer le choix de l'utilisateur
     * @param b le booléen
    */
    public void setConfirm(boolean b) {
        this.confirm = b;
    }

    /**
     * Affiche le JDialog et renvoie le choix de l'utilisateur
     * @return true si l'uilisateur a confirmé son choix, false sinon
     */
    public boolean getChoice() {
        this.setVisible(true);
        return this.confirm;
    }

}
