package be.msyben.vinylManager.gui;

import be.msyben.vinylManager.data.Data;
import be.msyben.vinylManager.entities.Album;
import be.msyben.vinylManager.entities.Collection;
import be.msyben.vinylManager.entities.Disque;
import be.msyben.vinylManager.entities.Titre;
import be.msyben.vinylManager.gui.icon.Icons;
import be.msyben.vinylManager.properties.Language;
import be.msyben.vinylManager.properties.Preferences;
import be.msyben.vinylManager.tools.swing.MyJList;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

/**
 * Fenetre de recherche
 *
 * @author Mathieu Syben
 */
public class SearchWindow extends JFrame {

    /**
     * uid
     */
    private static final long serialVersionUID = 9l;
    /**
     * Hauteur minimale
     */
    private static final int minHeight = 520;
    /**
     * Largeur minimale
     */
    private static final int minWidth = 500;
    /**
     * dernière largeur
     */
    private int lastWidth = 0;
    /**
     * dernière hauteur
     */
    private int lastHeight = 0;
    private JCheckBox cbArtiste = new JCheckBox(Language.getInstance().get("name.artiste"));//1
    private JCheckBox cbTitre = new JCheckBox(Language.getInstance().get("name.titre"));//2
    private JCheckBox cbPiste = new JCheckBox(Language.getInstance().get("name.piste"));//3
    private JCheckBox cbCompositeur = new JCheckBox(Language.getInstance().get("name.compositeur.full"));//4
    private JCheckBox cbChef = new JCheckBox(Language.getInstance().get("name.chef"));//5
    private JCheckBox cbOrchestre = new JCheckBox(Language.getInstance().get("name.orchestre"));//6
    private JCheckBox cbMusiciens = new JCheckBox(Language.getInstance().get("name.musiciens"));//7
    private JCheckBox cbEditeur = new JCheckBox(Language.getInstance().get("name.editeur"));//8
    private JCheckBox cbCommentaires = new JCheckBox(Language.getInstance().get("name.commentaire"));//9
    private JCheckBox cbGenre = new JCheckBox(Language.getInstance().get("name.genre"));//10
    private JCheckBox cbAnnee = new JCheckBox(Language.getInstance().get("name.annee"));//11
    private JCheckBox cbRef = new JCheckBox(Language.getInstance().get("name.reference"));//12
    private JCheckBox cbParolier = new JCheckBox(Language.getInstance().get("name.parolier"));//13
    private JCheckBox cbPays = new JCheckBox(Language.getInstance().get("name.pays"));//14
    private JCheckBox cbCouleur = new JCheckBox(Language.getInstance().get("name.couleur"));//15
    private JCheckBox cbLocation = new JCheckBox(Language.getInstance().get("name.location"));//16
    /**
     * Le label de recherche
     */
    JLabel l1 = new JLabel(Language.getInstance().get("search.text"));
    /**
     * Le champs de recherche
     */
    private JTextField searchField = new JTextField("");
    /**
     * Le scrollPane des résultats
     */
    private JScrollPane resultPane = new JScrollPane();
    /**
     * La liste des résultats
     */
    private JList<SearchElement> results = new MyJList<>();
    /**
     * Le bouton quitter
     */
    JButton quitter = new JButton(Language.getInstance().get("button.sortir"));

    /**
     * Creates a new instance of SearchWindow
     */
    public SearchWindow() {
        super(Language.getInstance().get("search.window.title"));
        MainWindow.getInstance().setEnabled(false);
        setIconImage(Icons.getInstance().icon.getImage());
        this.setLocationRelativeTo(null); // On centre la fenêtre sur l'ecran
        this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        this.getContentPane().setLayout(null);

        addComponentListener(new ComponentAdapter() {

            @Override
            public void componentResized(ComponentEvent e) {
                placeElements();
            }
        });

        putElements();
        setSize(minWidth, minHeight);
        setVisible(true);
    }

    /**
     * Place les éléments dans la fenêtre
     */
    private void placeElements() {

        int cbWidth = 180;

        int width = getWidth();

        int height = getHeight();
        boolean resize = false;
        if (width < minWidth) {
            width = minWidth;
            resize = true;
        }
        if (height < minHeight) {
            height = minHeight;
            resize = true;
        }
        if (resize) {
            setSize(width, height);
        }
        //System.out.print(lastWidth + ":" + lastHeight + " --> " + width + ":" + height + " --> ");
        if (width == lastWidth && height == lastHeight) {
            //System.out.println("Pas de changements");
            return;
        } else {
            //System.out.println("Resize");
            lastWidth = width;
            lastHeight = height;
        }

        l1.setBounds(5, 10, 200, 15);
        searchField.setBounds(205, 5, width - cbWidth - 225, 25);
        resultPane.setBounds(5, 50, width - cbWidth - 25, height - 130);
        results.setSize(width - cbWidth - 25, height - 130);
        quitter.setBounds((width - cbWidth - 50) / 2, height - 70, 100, 25);

        cbArtiste.setBounds(width - cbWidth + 5, 5, cbWidth - 10, 25);
        cbTitre.setBounds(width - cbWidth + 5, 35, cbWidth - 10, 25);
        cbPiste.setBounds(width - cbWidth + 5, 65, cbWidth - 10, 25);
        cbCompositeur.setBounds(width - cbWidth + 5, 95, cbWidth - 10, 25);
        cbChef.setBounds(width - cbWidth + 5, 125, cbWidth - 10, 25);
        cbOrchestre.setBounds(width - cbWidth + 5, 155, cbWidth - 10, 25);
        cbMusiciens.setBounds(width - cbWidth + 5, 185, cbWidth - 10, 25);
        cbEditeur.setBounds(width - cbWidth + 5, 215, cbWidth - 10, 25);
        cbCommentaires.setBounds(width - cbWidth + 5, 245, cbWidth - 10, 25);
        cbGenre.setBounds(width - cbWidth + 5, 275, cbWidth - 10, 25);
        cbAnnee.setBounds(width - cbWidth + 5, 305, cbWidth - 10, 25);
        cbRef.setBounds(width - cbWidth + 5, 335, cbWidth - 10, 25);
        cbParolier.setBounds(width - cbWidth + 5, 365, cbWidth - 10, 25);
        cbPays.setBounds(width - cbWidth + 5, 395, cbWidth - 10, 25);
        cbCouleur.setBounds(width - cbWidth + 5, 425, cbWidth - 10, 25);
        cbLocation.setBounds(width - cbWidth + 5, 455, cbWidth - 10, 25);


    }

    /**
     * Ajoute les éléments dans la fenêtre
     */
    private void putElements() {

        Container c = this.getContentPane();


        c.add(l1);

        c.add(searchField);
        searchField.addKeyListener(new KeyAdapter() {

            @Override
            public void keyReleased(KeyEvent e) {
                search();
            }
        });

        results.addListSelectionListener(new ListSelectionListener() {

            @Override
            public void valueChanged(ListSelectionEvent e) {
                if (!e.getValueIsAdjusting()) {

                    SearchElement se = (SearchElement) results.getSelectedValue();
                    if (se != null) {
                        if (se.getDisque() == null) {
                            MainWindow.getInstance().select(se.getAlbum(), 0);
                        } else {
                            MainWindow.getInstance().select(se.getAlbum(), se.getDisque().getNum() - 1);
                        }
                    }
                }
            }
        });


        resultPane.getViewport().setView(results);
        c.add(resultPane);


        c.add(quitter);
        quitter.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                MainWindow.getInstance().setEnabled(true);
                dispose();
            }
        });

        this.addWindowListener(new WindowAdapter() {

            @Override
            public void windowClosing(WindowEvent e) {
                MainWindow.getInstance().setEnabled(true);
                dispose();
            }
        });


        String searchParams = Preferences.getInstance().get(Preferences.SEARCH_PARAMS, "1,2,3");
        String[] paramsSplit = searchParams.split(",");
        for (String s : paramsSplit) {
            try {
                int cbId = Integer.parseInt(s);
                switch (cbId) {
                    case 1:
                        cbArtiste.setSelected(true);
                        break;
                    case 2:
                        cbTitre.setSelected(true);
                        break;
                    case 3:
                        cbPiste.setSelected(true);
                        break;
                    case 4:
                        cbCompositeur.setSelected(true);
                        break;
                    case 5:
                        cbChef.setSelected(true);
                        break;
                    case 6:
                        cbOrchestre.setSelected(true);
                        break;
                    case 7:
                        cbMusiciens.setSelected(true);
                        break;
                    case 8:
                        cbEditeur.setSelected(true);
                        break;
                    case 9:
                        cbCommentaires.setSelected(true);
                        break;
                    case 10:
                        cbGenre.setSelected(true);
                        break;
                    case 11:
                        cbAnnee.setSelected(true);
                        break;
                    case 12:
                        cbRef.setSelected(true);
                        break;
                    case 13:
                        cbParolier.setSelected(true);
                        break;
                    case 14:
                        cbPays.setSelected(true);
                        break;
                    case 15:
                        cbCouleur.setSelected(true);
                        break;
                    case 16:
                        cbLocation.setSelected(true);
                        break;
                    default:
                        break;
                }
            } catch (NumberFormatException ex) {
            }
        }

        ActionListener cbAL = new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                String params = "";
                if (cbArtiste.isSelected()) {
                    if (!params.isEmpty()) {
                        params += ",";
                    }
                    params += "1";
                }
                if (cbTitre.isSelected()) {
                    if (!params.isEmpty()) {
                        params += ",";
                    }
                    params += "2";
                }
                if (cbPiste.isSelected()) {
                    if (!params.isEmpty()) {
                        params += ",";
                    }
                    params += "3";
                }
                if (cbCompositeur.isSelected()) {
                    if (!params.isEmpty()) {
                        params += ",";
                    }
                    params += "4";
                }
                if (cbChef.isSelected()) {
                    if (!params.isEmpty()) {
                        params += ",";
                    }
                    params += "5";
                }
                if (cbOrchestre.isSelected()) {
                    if (!params.isEmpty()) {
                        params += ",";
                    }
                    params += "6";
                }
                if (cbMusiciens.isSelected()) {
                    if (!params.isEmpty()) {
                        params += ",";
                    }
                    params += "7";
                }
                if (cbEditeur.isSelected()) {
                    if (!params.isEmpty()) {
                        params += ",";
                    }
                    params += "8";
                }
                if (cbCommentaires.isSelected()) {
                    if (!params.isEmpty()) {
                        params += ",";
                    }
                    params += "9";
                }
                if (cbGenre.isSelected()) {
                    if (!params.isEmpty()) {
                        params += ",";
                    }
                    params += "10";
                }
                if (cbAnnee.isSelected()) {
                    if (!params.isEmpty()) {
                        params += ",";
                    }
                    params += "11";
                }
                if (cbRef.isSelected()) {
                    if (!params.isEmpty()) {
                        params += ",";
                    }
                    params += "12";
                }
                if (cbParolier.isSelected()) {
                    if (!params.isEmpty()) {
                        params += ",";
                    }
                    params += "13";
                }
                if (cbPays.isSelected()) {
                    if (!params.isEmpty()) {
                        params += ",";
                    }
                    params += "14";
                }
                if (cbCouleur.isSelected()) {
                    if (!params.isEmpty()) {
                        params += ",";
                    }
                    params += "15";
                }
                if (cbLocation.isSelected()) {
                    if (!params.isEmpty()) {
                        params += ",";
                    }
                    params += "16";
                }
                Preferences.getInstance().set(Preferences.SEARCH_PARAMS, params);

                search();
            }
        };
        cbArtiste.addActionListener(cbAL);
        cbTitre.addActionListener(cbAL);
        cbPiste.addActionListener(cbAL);
        cbCompositeur.addActionListener(cbAL);
        cbChef.addActionListener(cbAL);
        cbOrchestre.addActionListener(cbAL);
        cbMusiciens.addActionListener(cbAL);
        cbEditeur.addActionListener(cbAL);
        cbCommentaires.addActionListener(cbAL);
        cbGenre.addActionListener(cbAL);
        cbAnnee.addActionListener(cbAL);
        cbRef.addActionListener(cbAL);
        cbParolier.addActionListener(cbAL);
        cbPays.addActionListener(cbAL);
        cbCouleur.addActionListener(cbAL);
        cbLocation.addActionListener(cbAL);

        c.add(cbArtiste);
        c.add(cbTitre);
        c.add(cbPiste);
        c.add(cbCompositeur);
        c.add(cbChef);
        c.add(cbOrchestre);
        c.add(cbMusiciens);
        c.add(cbEditeur);
        c.add(cbCommentaires);
        c.add(cbGenre);
        c.add(cbAnnee);
        c.add(cbRef);
        c.add(cbParolier);
        c.add(cbPays);
        c.add(cbCouleur);
        c.add(cbLocation);



    }

    /**
     * Méthode de recherche
     */
    private void search() {
        Collection c = Data.getInstance().getCollection();
        String search = searchField.getText().toLowerCase();
        results.setListData(new SearchElement[0]);

        if (!cbArtiste.isSelected()
                && !cbTitre.isSelected()
                && !cbPiste.isSelected()
                && !cbCompositeur.isSelected()
                && !cbChef.isSelected()
                && !cbOrchestre.isSelected()
                && !cbMusiciens.isSelected()
                && !cbEditeur.isSelected()
                && !cbCommentaires.isSelected()
                && !cbGenre.isSelected()
                && !cbAnnee.isSelected()
                && !cbRef.isSelected()
                && !cbParolier.isSelected()
                && !cbPays.isSelected()
                && !cbCouleur.isSelected()
                && !cbLocation.isSelected()) {
            return;
        }

        if (search.length() > 0) {

            List<SearchElement> res = new ArrayList<>();

            loop:
            for (Album a : c.getAlbums()) {
                if (cbTitre.isSelected()) {
                    if (a.getTitre().toLowerCase().contains(search)) {
                        res.add(new SearchElement(a));
                        continue loop;
                    }
                }
                if (cbArtiste.isSelected()) {
                    if (a.getArtiste() != null && a.getArtiste().toLowerCase().contains(search)) {
                        res.add(new SearchElement(a));
                        continue loop;
                    }
                }
                if (cbPiste.isSelected()) {
                    for (Disque d : a.getDisques()) {
                        for (Titre t : d.getFaceA()) {
                            if (t.getNom().toLowerCase().contains(search)) {
                                res.add(new SearchElement(a, d));
                                continue loop;
                            }
                            if (t.getArtiste() != null && t.getArtiste().toLowerCase().contains(search)) {
                                res.add(new SearchElement(a, d));
                                continue loop;
                            }
                        }
                        for (Titre t : d.getFaceB()) {
                            if (t.getNom().toLowerCase().contains(search)) {
                                res.add(new SearchElement(a, d));
                                continue loop;
                            }
                            if (t.getArtiste() != null && t.getArtiste().toLowerCase().contains(search)) {
                                res.add(new SearchElement(a, d));
                                continue loop;
                            }
                        }
                    }
                }
                if (cbCompositeur.isSelected()) {
                    if (a.getCompositeur() != null && a.getCompositeur().toLowerCase().contains(search)) {
                        res.add(new SearchElement(a));
                        continue loop;
                    }
                }
                if (cbChef.isSelected()) {
                    if (a.getChef() != null && a.getChef().toLowerCase().contains(search)) {
                        res.add(new SearchElement(a));
                        continue loop;
                    }
                }
                if (cbOrchestre.isSelected()) {
                    if (a.getOrchestre() != null && a.getOrchestre().toLowerCase().contains(search)) {
                        res.add(new SearchElement(a));
                        continue loop;
                    }
                }
                if (cbMusiciens.isSelected()) {
                    if (a.getMusiciens() != null && a.getMusiciens().toLowerCase().contains(search)) {
                        res.add(new SearchElement(a));
                        continue loop;
                    }
                }
                if (cbEditeur.isSelected()) {
                    if (a.getEditeur() != null && a.getEditeur().toLowerCase().contains(search)) {
                        res.add(new SearchElement(a));
                        continue loop;
                    }
                }
                if (cbCommentaires.isSelected()) {
                    if (a.getCommentaire() != null && a.getCommentaire().toLowerCase().contains(search)) {
                        res.add(new SearchElement(a));
                        continue loop;
                    }
                }
                if (cbGenre.isSelected()) {
                    if (a.getGenre() != null && a.getGenre().toLowerCase().contains(search)) {
                        res.add(new SearchElement(a));
                        continue loop;
                    }
                }
                if (cbAnnee.isSelected()) {
                    if (a.getAnnee() != null && a.getAnnee().toLowerCase().contains(search)) {
                        res.add(new SearchElement(a));
                        continue loop;
                    }
                }
                if (cbRef.isSelected()) {
                    if (a.getReference() != null && a.getReference().toLowerCase().contains(search)) {
                        res.add(new SearchElement(a));
                        continue loop;
                    }
                }
                if (cbParolier.isSelected()) {
                    if (a.getParolier()!= null && a.getParolier().toLowerCase().contains(search)) {
                        res.add(new SearchElement(a));
                        continue loop;
                    }
                }
                if (cbPays.isSelected()) {
                    if (a.getPays()!= null && a.getPays().toLowerCase().contains(search)) {
                        res.add(new SearchElement(a));
                        continue loop;
                    }
                }
                if (cbCouleur.isSelected()) {
                    for (Disque d : a.getDisques()) {
                        if (d.getCouleur()!= null && d.getCouleur().toLowerCase().contains(search)) {
                            res.add(new SearchElement(a));
                            continue loop;
                        }
                    }
                }
                if (cbLocation.isSelected()) {
                    if (a.getLocation()!= null && a.getLocation().toLowerCase().contains(search)) {
                        res.add(new SearchElement(a));
                        continue loop;
                    }
                }
            }

            if (res.size() > 0) {
                Collections.sort(res);
                results.setListData(res.toArray(new SearchElement[0]));
            }
        }
    }
}

/**
 * Inner class pour la représentation des résultats de la recherche.
 */
class SearchElement implements Comparable<SearchElement> {

    /**
     * Constructeur *
     */
    public SearchElement() {
    }

    /**
     * Constructeur
     *
     * @param artist l'artiste
     * @param album l'album
     */
    public SearchElement(Album album) {
        this.album = album;
    }

    /**
     * Constructeur
     *
     * @param artist l'artiste
     * @param album l'album
     * @param disque le disque
     */
    public SearchElement(Album album, Disque disque) {
        this.album = album;
        this.disque = disque;
    }
    /**
     * Holds value of property album.
     */
    private Album album;

    /**
     * Getter for property album.
     *
     * @return Value of property album.
     */
    public Album getAlbum() {
        return this.album;
    }

    /**
     * Setter for property album.
     *
     * @param album New value of property album.
     */
    public void setAlbum(Album album) {
        this.album = album;
    }

    /**
     * to String
     *
     * @return string representation
     */
    @Override
    public String toString() {
        return album.getArtisteForList() + " -- " + album.getAnnee() + " - " + album.getTitre();
    }

    /**
     * Compare 2 SearchElement
     *
     * @param s l'élément à comparer avec l'élément courant
     * @return un entier correspondant à la comparaison
     */
    @Override
    public int compareTo(SearchElement s) {
        if (album.getArtiste() == null)  {
            return -1;
        } 
        if (s == null || s.getAlbum() == null || s.getAlbum().getArtiste() == null) {
            return 1;
        }
        int art = album.getArtiste().compareTo(s.getAlbum().getArtiste());
        if (art == 0) {
            return album.getTitre().compareTo(s.getAlbum().getTitre());
        } else {
            return art;
        }
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final SearchElement other = (SearchElement) obj;
        
        return new EqualsBuilder().append(this.getAlbum().getArtiste(), other.getAlbum().getArtiste()).
                append(this.getAlbum().getTitre(), other.getAlbum().getTitre()).isEquals();
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(this.album.getArtiste()).append(this.album.getTitre()).hashCode();
    }
    
    
    
    /**
     * Holds value of property disque.
     */
    private Disque disque;

    /**
     * Getter for property disque.
     *
     * @return Value of property disque.
     */
    public Disque getDisque() {
        return this.disque;
    }

    /**
     * Setter for property disque.
     *
     * @param disque New value of property disque.
     */
    public void setDisque(Disque disque) {
        this.disque = disque;
    }
}
