/*
Copyright 2005-2013 Samuel Gesche

This file is part of ArcEnCiel.

ArcEnCiel is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

ArcEnCiel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with ArcEnCiel.  If not, see <http://www.gnu.org/licenses/>.
*/

package ihm;

import data.ListeSynonymes;
import data.Confrontation;
import data.TexteCommun;

import ihm.Legende;

import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JTextArea;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JButton;
import javax.swing.ListCellRenderer;

import java.awt.Color;
import java.awt.Component;
import java.awt.BorderLayout;
import java.awt.FlowLayout;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.util.Vector;

/**
 * Cette classe est le conteneur des dialogues offerts lors de la séparation ou
 * le rapprochement de termes. Ces dialogues fournissent les annotations
 * multi-documents qui sont l'essence de la confrontation.<br>
 *
 * @author Samuel GESCHE
 * @version 3.5.1
 * @since 3.0.3
 */
public class DialogueAnnotation extends JDialog {
    private JComboBox cReponses;
    private JTextArea tComm;
    private JTextField tPrecis;
    private boolean canceled = false;
    private JPanel pMain;
    private JList lRepartition;
    private JPanel pRepartition;
    private Legende legende;
    private Vector repartition;

    /**
     * Crée un dialogue pour la levée d'ambiguités quand l'utilisateur sépare
     * plusieurs composantes dans un terme alors que le terme fusionné est
     * utilisé dans des liens par ailleurs.
     * @param parentComponent Component le composant dans lequel afficher le
     * dialogue
     * @param liste ListeSynonymes une liste contenant le terme
     * @param repartition TexteCommun[] la nouvelle répartition du terme en
     * termes de nuances
     * @param desc String la phrase explicative à afficher
     * @since 3.0.5
     */
    public DialogueAnnotation(Component parentComponent, ListeSynonymes liste,
                              TexteCommun[] repartition, String desc) {
        super(JOptionPane.getFrameForComponent(parentComponent), true);
        getContentPane().setLayout(new BorderLayout());
        setUndecorated(true);

        pMain = new JPanel(new BorderLayout());
        pMain.setBorder(Charte.getBorder());

        JPanel pMain2 = new JPanel(new BorderLayout());

        JPanel pNord = new JPanel(new BorderLayout());

        JLabel lQuestion = new JLabel(desc, JLabel.CENTER);
        pNord.add(lQuestion, BorderLayout.NORTH);

        JPanel pSujet = new JPanel(new FlowLayout());
        legende = new Legende(liste.getListe()[0].getConcernes().length);
        for (int i = 0; i < liste.getListe().length; i++) {
            JLabel l1 = legende.getClasseur(liste.getListe()[i].getConcernes());
            JLabel l2 = new JLabel(liste.getListe()[i].getTexte());
            Charte.formate(l2);
            pSujet.add(l1);
            pSujet.add(l2);
        }
        pSujet.add(new JLabel("{" + liste.getLien() + "}"));
        pNord.add(pSujet, BorderLayout.SOUTH);

        pMain2.add(pNord, BorderLayout.NORTH);

        JPanel pCenter = new JPanel(new BorderLayout());

        cReponses = new JComboBox(repartition);
        cReponses.setRenderer(new ListCellRenderer() {
            public Component getListCellRendererComponent(JList list,
                    Object value, int index, boolean isSelected,
                    boolean cellHasFocus) {
                JLabel res = legende.getClasseur(((TexteCommun) value).
                                                 getConcernes());
                Charte.formate(res);
                JLabel res2 = new JLabel(((TexteCommun) value).getTexte());
                Charte.formate(res2);
                if (isSelected) {
                    res.setOpaque(true);
                    res.setBackground(new Color(0, 0, 0, 64));
                    res2.setOpaque(true);
                    res2.setBackground(new Color(0, 0, 0, 64));
                }
                JPanel p = new JPanel(new BorderLayout());
                p.add(res, BorderLayout.WEST);
                p.add(res2, BorderLayout.CENTER);
                Charte.formate(p);
                return p;
            }
        });
        pCenter.add(cReponses, BorderLayout.NORTH);

        JLabel lComm = new JLabel(Charte.getMessage("Anno_Comment"), JLabel.CENTER);
        pCenter.add(lComm, BorderLayout.CENTER);

        tComm = new JTextArea(liste.getCommentaire(), 10, 20);
        tComm.setLineWrap(true);
        tComm.setWrapStyleWord(true);
        tComm.setAutoscrolls(false);
        JScrollPane spComm = new JScrollPane(tComm);
        Charte.formate(spComm);
        Charte.formate(spComm.getViewport());
        Charte.formate(spComm.getHorizontalScrollBar());
        Charte.formate(spComm.getVerticalScrollBar());
        pCenter.add(spComm, BorderLayout.CENTER);

        pMain2.add(pCenter, BorderLayout.CENTER);

        JPanel pBoutons = new JPanel(new FlowLayout());

        JButton bOK = new JButton(Charte.OK);
        pBoutons.add(bOK);
        bOK.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                canceled = false;
                setVisible(false);
            }
        });

        pMain.add(pMain2, BorderLayout.CENTER);
        pMain.add(pBoutons, BorderLayout.SOUTH);

        getContentPane().add(pMain, BorderLayout.CENTER);

        pack();
        int x = parentComponent.getX() +
                (parentComponent.getWidth() - this.getWidth()) / 2;
        int y = parentComponent.getY() +
                (parentComponent.getHeight() - this.getHeight()) / 2;
        setLocation(x, y);
        bOK.requestFocus();
    }

    /**
     * Crée un dialogue pour la séparation d'un terme.
     * @param parentComponent Component le composant dans lequel afficher le
     * dialogue
     * @param mot TexteCommun le terme à séparer
     * @param desc String la phrase explicative à afficher
     * @param choix String[] les justifications possibles
     * @since 3.0.4
     */
    public DialogueAnnotation(Component parentComponent, TexteCommun mot,
                              String desc, String[] choix) {
        this(parentComponent, desc, choix);

        legende = new Legende(mot.getConcernes().length);

        JPanel pMain3 = new JPanel(new BorderLayout());

        pRepartition = new JPanel(new BorderLayout());
        repartition = new Vector();
        for (int i = 0; i < mot.getConcernes().length; i++) {
            if (mot.getConcernes()[i] == true) {
                TexteCommun t = new TexteCommun(mot.getTexte(),
                                                mot.getConcernes().length);
                t.addConcerne(i, true);
                repartition.addElement(t);
            }
        }
        remplisListe();
        pMain3.add(pRepartition, BorderLayout.CENTER);

        JButton bFus = new JButton(Charte.getMessage("Anno_Fusion"));
        bFus.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                fusion();
            }
        });

        JButton bDiv = new JButton(Charte.getMessage("Anno_Separer"));
        bDiv.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                division();
            }
        });

        JPanel pB = new JPanel(new FlowLayout());
        pB.add(bFus);
        pB.add(bDiv);
        pMain3.add(pB, BorderLayout.SOUTH);

        pMain.add(pMain3, BorderLayout.NORTH);

        pack();
        int x = parentComponent.getX() +
                (parentComponent.getWidth() - this.getWidth()) / 2;
        int y = parentComponent.getY() +
                (parentComponent.getHeight() - this.getHeight()) / 2;
        setLocation(x, y);
    }

    /**
     * Crée un dialogue pour le reliement de termes.
     * @param parentComponent Component le composant dans lequel afficher le
     * dialogue
     * @param desc String la phrase explicative à afficher
     * @param choix String[] les justifications possibles
     * @since 3.0.3
     */
    public DialogueAnnotation(Component parentComponent, String desc,
                              String[] choix) {
        super(JOptionPane.getFrameForComponent(parentComponent), true);
        getContentPane().setLayout(new BorderLayout());
        setUndecorated(true);

        pMain = new JPanel(new BorderLayout());
        pMain.setBorder(Charte.getBorder());

        JPanel pMain2 = new JPanel(new BorderLayout());

        JPanel pNord = new JPanel(new BorderLayout());

        JLabel lQuestion = new JLabel(desc, JLabel.CENTER);
        pNord.add(lQuestion, BorderLayout.NORTH);

        cReponses = new JComboBox(choix);
        pNord.add(cReponses, BorderLayout.CENTER);

        JPanel pPrecis = new JPanel(new BorderLayout());
        JLabel lPrecis = new JLabel(Charte.getMessage("Anno_AutreRaison")+" ");
        tPrecis = new JTextField(20);
        pPrecis.add(lPrecis, BorderLayout.WEST);
        pPrecis.add(tPrecis, BorderLayout.EAST);
        pNord.add(pPrecis, BorderLayout.SOUTH);

        pMain2.add(pNord, BorderLayout.NORTH);

        JPanel pCenter = new JPanel(new BorderLayout());

        JLabel lComm = new JLabel(Charte.getMessage("Anno_Comment"), JLabel.CENTER);
        pCenter.add(lComm, BorderLayout.NORTH);

        tComm = new JTextArea(10, 20);
        tComm.setLineWrap(true);
        tComm.setWrapStyleWord(true);
        tComm.setAutoscrolls(false);
        JScrollPane spComm = new JScrollPane(tComm);
        Charte.formate(spComm);
        Charte.formate(spComm.getViewport());
        Charte.formate(spComm.getHorizontalScrollBar());
        Charte.formate(spComm.getVerticalScrollBar());
        pCenter.add(spComm, BorderLayout.CENTER);

        pMain2.add(pCenter, BorderLayout.CENTER);

        JPanel pBoutons = new JPanel(new FlowLayout());

        JButton bOK = new JButton(Charte.OK);
        pBoutons.add(bOK);
        bOK.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                canceled = false;
                setVisible(false);
            }
        });

        JButton bCancel = new JButton(Charte.CANCEL);
        pBoutons.add(bCancel);
        bCancel.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                canceled = true;
                setVisible(false);
            }
        });

        pMain.add(pMain2, BorderLayout.CENTER);
        pMain.add(pBoutons, BorderLayout.SOUTH);

        getContentPane().add(pMain, BorderLayout.CENTER);

        pack();
        int x = parentComponent.getX() +
                (parentComponent.getWidth() - this.getWidth()) / 2;
        int y = parentComponent.getY() +
                (parentComponent.getHeight() - this.getHeight()) / 2;
        setLocation(x, y);
        bOK.requestFocus();
    }

    /**
     * Renvoie le choix effectué, c'est à dire soit la valeur choisie parmi
     * celle fournies à la création, soit une nouvelle valeur si la valeur
     * choisie est Confrontation.RAISON_A_PRECISER.
     * @return String le choix effectué
     * @since 3.0.3
     */
    public String getChoix() {
        String resultat = "";
        if (cReponses.getSelectedItem().toString().equals(
                Confrontation.RAISON_A_PRECISER)) {
            resultat = tPrecis.getText();
        } else {
            resultat = cReponses.getSelectedItem().toString();
        }
        return resultat;
    }

    /**
     * Renvoie le terme choisi parmi ceux qui ont été donnés à la construction.
     * Il s'agit ici de la désambiguation de liens lors d'une séparation.
     * @return TexteCommun le choix effectué
     * @since 3.0.5
     */
    public TexteCommun getTexteCommunChoisi() {
        return (TexteCommun) (cReponses.getSelectedItem());
    }

    /**
     * Renvoie le commentaire tapé par l'utilisateur.
     * @return String le commentaire en question
     * @since 3.0.3
     */
    public String getCommentaires() {
        return tComm.getText();
    }

    /**
     * Renvoie la répartition effectuée par l'utilisateur lors de la séparation
     * d'un terme.
     * @return TexteCommun[] la répartition en question
     * @since 3.0.4
     */
    public TexteCommun[] getRepartition() {
        TexteCommun[] t = new TexteCommun[repartition.size()];
        repartition.toArray(t);
        return t;
    }

    /**
     * Renvoie vrai si l'utilisateur a annulé le dialogue (soit en appuyant sur
     * le bouton correspondant, soit en fermant la fenêtre.
     * @return boolean si le dialogue a été annulé ou non
     * @since 3.0.3
     */
    public boolean isAnnule() {
        return canceled;
    }

    private void remplisListe() {
        pRepartition.removeAll();
        TexteCommun[] t = new TexteCommun[repartition.size()];
        repartition.toArray(t);
        lRepartition = new JList(t);
        lRepartition.setSelectionMode(javax.swing.ListSelectionModel.
                                      MULTIPLE_INTERVAL_SELECTION);
        lRepartition.setCellRenderer(new ListCellRenderer() {
            public Component getListCellRendererComponent(JList list,
                    Object value, int index, boolean isSelected,
                    boolean cellHasFocus) {
                JLabel res = legende.getClasseur(((TexteCommun) value).
                                                 getConcernes());
                Charte.formate(res);
                JLabel res2 = new JLabel(((TexteCommun) value).getTexte());
                Charte.formate(res2);
                if (isSelected) {
                    res.setOpaque(true);
                    res.setBackground(new Color(0, 0, 0, 64));
                    res2.setOpaque(true);
                    res2.setBackground(new Color(0, 0, 0, 64));
                }
                JPanel p = new JPanel(new BorderLayout());
                p.add(res, BorderLayout.WEST);
                p.add(res2, BorderLayout.CENTER);
                p.setOpaque(false);
                return p;
            }
        });
        pRepartition.add(lRepartition, BorderLayout.CENTER);
        pack();
    }

    /* Bouton "Fusion" de la séparation.*/
    private void fusion() {
        TexteCommun[] liste = new TexteCommun[
                              lRepartition.getSelectedIndices().length];
        for (int i = 0; i < liste.length; i++) {
            liste[i] = (TexteCommun)
                       (lRepartition.getModel().getElementAt(
                               lRepartition.getSelectedIndices()[i]));
        }
        TexteCommun res = new TexteCommun(liste[0].getTexte(),
                                          liste[0].getConcernes().length);
        for (int i = 0; i < liste.length; i++) {
            for (int j = 0; j < liste[0].getConcernes().length; j++) {
                if (liste[i].getConcernes()[j] == true) {
                    res.addConcerne(j, true);
                }
            }
        }
        for (int i = 0; i < repartition.size(); i++) {
            for (int k = 0; k < liste.length; k++) {
                boolean[] b0 = liste[k].getConcernes();
                boolean[] b1 = ((TexteCommun)
                                (repartition.elementAt(i))).getConcernes();
                boolean bon = true;
                for (int j = 0; j < b0.length; j++) {
                    if (b0[j] != b1[j]) {
                        bon = false;
                    }
                }
                if (bon) {
                    repartition.removeElementAt(i);
                }
            }
        }
        repartition.add(res);
        remplisListe();
    }

    /* Bouton "division" de la séparation. */
    private void division() {
        TexteCommun liste = (TexteCommun) (lRepartition.getSelectedValue());
        for (int i = 0; i < repartition.size(); i++) {
            boolean[] b0 = liste.getConcernes();
            boolean[] b1 = ((TexteCommun)
                            (repartition.elementAt(i))).getConcernes();
            boolean bon = true;
            for (int j = 0; j < b0.length; j++) {
                if (b0[j] != b1[j]) {
                    bon = false;
                }
            }
            if (bon) {
                repartition.removeElementAt(i);
                break;
            }
        }
        for (int i = 0; i < liste.getConcernes().length; i++) {
            if (liste.getConcernes()[i] == true) {
                TexteCommun t = new TexteCommun(liste.getTexte(),
                                                liste.getConcernes().length);
                t.addConcerne(i, true);
                repartition.addElement(t);
            }
        }
        remplisListe();
    }
}
