/*
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.Confrontation;
import data.Graphe;
import data.Lien;
import data.Noeud;
import data.Association;
import ihm.townto.GraphPanel;
import ihm.townto.Graph;
import ihm.townto.LinkFailureException;
import ihm.townto.EventHandler;
import ihm.townto.EventListener;

import javax.swing.JOptionPane;
import javax.swing.JTabbedPane;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.JSplitPane;
import javax.swing.JLabel;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.ListSelectionEvent;

import java.awt.Component;
import java.awt.Color;
import java.awt.Dimension;

/**
 * Oui parce que ça commence à devenir lourd, tout ce code dans la fenêtre
 * principale.
 * <br>
 * Nous allons donc définir ici un composant présentant un graphe. L'objectif
 * est de pouvoir visualiser ce graphe avant de se préoccuper de confrontation.
 * <br>
 * Il y aura donc à gauche la liste des noeuds (quel que soit leur appellation
 * dans le formalisme initial), ainsi que la liste des types de liens. Ces deux
 * listes fournissent les principales données sur le graphe. Au centre, on
 * aura une portion du graphe en question, centrée sur le concept que l'on
 * choisira dans la liste à gauche.
 * <br>
 * Voilà...
 *
 *
 * @author Samuel GESCHE
 * @version 3.0
 */
public class PanelVisualisation extends JTabbedPane implements EventListener {
    private final Confrontation conf;
    private final GraphPanel[] gPanel;

    public PanelVisualisation(Confrontation confrontation) {
        super(JTabbedPane.TOP, JTabbedPane.WRAP_TAB_LAYOUT);
        Charte.formate(this);
        this.conf = confrontation;
        this.gPanel = new GraphPanel[conf.getNombreDeGraphes()];
        EventHandler.register(this);

        final Legende legende = new Legende(confrontation.getAllNomsGraphes());

        for (int i = 0; i < confrontation.getNombreDeGraphes(); i++) {
            JSplitPane pVisuGraphe = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
            Charte.formate(pVisuGraphe);
            pVisuGraphe.setContinuousLayout(true);

            Noeud[] noeuds = confrontation.getGrapheAt(i).getAllNoeuds();
            final JList lNoeuds = new JList(noeuds);
            Charte.formate(lNoeuds);
            lNoeuds.setDragEnabled(true);
            lNoeuds.setCellRenderer(new ListCellRenderer() {
                public Component getListCellRendererComponent(JList list,
                        Object value,
                        int index, boolean isSelected, boolean cellHasFocus) {
                    JLabel res = new JLabel(((Noeud)value).getLabel());
                    Charte.formate(res);
                    if (isSelected) {
                        res.setOpaque(true);
                        res.setBackground(new Color(0, 0, 0, 64));
                    }
                    return res;
                }
            });
            JScrollPane jspNoeuds = new JScrollPane(lNoeuds);
            Charte.formate(jspNoeuds);
            Charte.formate(jspNoeuds.getViewport());
            Charte.formate(jspNoeuds.getHorizontalScrollBar());
            Charte.formate(jspNoeuds.getVerticalScrollBar());
            pVisuGraphe.setLeftComponent(jspNoeuds);

            final int j = i;

            Graph graph = remplissageGraphe(confrontation, j,
                                            confrontation.getGrapheAt(j).
                                            getAllNoeuds()[0]);
            if (!(graph.isExhaustive()) && this.hasFocus()) {
                JOptionPane.showMessageDialog(this,
                                              Charte.getMessage("PanelConf_GrapheTropGros"),
                                              Charte.getMessage("PanelConf_GrapheTropGrosT"),
                                              JOptionPane.INFORMATION_MESSAGE,
                                              Charte.getSmiley(Charte.MITIGE));
            }
            gPanel[j] = new GraphPanel(graph, i);
            JScrollPane spGraphe = new JScrollPane(gPanel[j]) {
                public Dimension getPreferredSize() {
                    // Oui parce que sinon ça prend toute la place...
                    return new Dimension((int) (this.getSize().width * 0.8),
                                         this.getSize().height);
                }
            };
            Charte.formate(spGraphe);
            Charte.formate(spGraphe.getViewport());
            Charte.formate(spGraphe.getHorizontalScrollBar());
            Charte.formate(spGraphe.getVerticalScrollBar());

            lNoeuds.addListSelectionListener(new ListSelectionListener() {
                public void valueChanged(ListSelectionEvent lse) {
                    gPanel[j].setGraph(remplissageGraphe(conf, j,
                            (Noeud)(lNoeuds.getSelectedValue())));
                }
            });

            pVisuGraphe.setRightComponent(/*gPanel[j]*/ spGraphe);
            addTab(confrontation.getGrapheAt(i).getNom(),
                   legende.getIconeIndicateur(i),
                   pVisuGraphe);
            pVisuGraphe.setDividerSize(5);
            pVisuGraphe.setDividerLocation(0.20);
        }
        for (int i = 0; i < getTabCount(); i++) {
            setBackgroundAt(i, new Color(0, 0, 0, 64));
        }
        setOpaque(false);
    }

    public void notifyEvent(int eventCode, String eventContent){
        if(eventCode / 1000 == 1) {
            int cnf = eventCode - 1000;
            gPanel[cnf].setGraph(remplissageGraphe(conf, cnf, conf.getGrapheAt(cnf).trouveNoeud(eventContent)));
        }
    }

    private Graph remplissageGraphe(Confrontation cnf, int grp, Noeud cnt) {
        Graphe g = cnf.getGrapheAt(grp);
        Graph res = new Graph();
        res.setActive(cnt.getLabel(), cnt.getDescription());

        Association[] cour1 = g.getAssociationsContenant(cnt);
        for (int i = 0; i < cour1.length; i++) {
            try {
                Noeud o = cour1[i].getOrigine();
                Noeud d = cour1[i].getDestination();
                Lien l = cour1[i].getLien();
                if (o.getLabel().equals(cnt.getLabel())) {
                    Association[] cour2 = g.getAssociationsContenant(d);
                    res.addLink(cnt.getLabel(), cnt.getDescription(), 0, d.getLabel(),
                                d.getDescription(), cour2.length, l.getLabel() + " (" +
                                l.getType().getNom() + ")");
                    /*for(int j=0; j<cour2.length; j++){
                        Noeud o2 = cour2[j].getOrigine();
                        Noeud d2 = cour2[j].getDestination();
                        Lien l2 = cour2[j].getLien();
                        if(o2.getLabel().equals(d.getLabel())){
                            res.addLink(d.getLabel(), cour2.length, d2.getLabel(), 0, l2.getLabel() + " (" +
                                l2.getType().getNom() + ")", "");
                        } else if(d2.getLabel().equals(d.getLabel())){
                            res.addLink(o2.getLabel(), cour2.length, d.getLabel(), 0, l2.getLabel() + " (" +
                                l2.getType().getNom() + ")", "");
                        }
                    }*/
                } else if (d.getLabel().equals(cnt.getLabel())) {
                    Association[] cour2 = g.getAssociationsContenant(o);
                    res.addLink(o.getLabel(), o.getDescription(), cour2.length,
                                cnt.getLabel(), cnt.getDescription(), 0, l.getLabel() + " (" +
                                l.getType().getNom() + ")");
                    /*for(int j=0; j<cour2.length; j++){
                        Noeud o2 = cour2[j].getOrigine();
                        Noeud d2 = cour2[j].getDestination();
                        Lien l2 = cour2[j].getLien();
                        if(o2.getLabel().equals(o.getLabel())){
                            res.addLink(o.getLabel(), cour2.length, d2.getLabel(), 0, l2.getLabel() + " (" +
                                l2.getType().getNom() + ")", "");
                        } else if(d2.getLabel().equals(o.getLabel())){
                            res.addLink(o2.getLabel(), cour2.length, o.getLabel(), 0, l2.getLabel() + " (" +
                                l2.getType().getNom() + ")", "");
                        }
                    }*/

                }
            } catch (LinkFailureException lfe) {
                // Erreur de création de lien
                /*JOptionPane.showMessageDialog(null,
                        "Problème de construction du graphe visualisé (" +
                                              lfe.getMessage() + ")",
                                              "Erreur de lecture",
                                              JOptionPane.ERROR_MESSAGE);
                lfe.printStackTrace();*/

            }
        }
        return res;
    }


}
