package be.msyben.vinylManager.gui;

import be.msyben.vinylManager.aide.AideMenuItem;
import be.msyben.vinylManager.controller.Controller;
import be.msyben.vinylManager.data.Data;
import be.msyben.vinylManager.entities.Album;
import be.msyben.vinylManager.entities.Disque;
import be.msyben.vinylManager.entities.Titre;
import be.msyben.vinylManager.exceptions.VinylManagerException;
import be.msyben.vinylManager.gui.icon.Icons;
import be.msyben.vinylManager.gui.list.albumList.AbstractAlbumList;
import be.msyben.vinylManager.gui.list.albumList.AlbumList;
import be.msyben.vinylManager.gui.list.albumList.AlbumListListener;
import be.msyben.vinylManager.gui.list.leftList.*;
import be.msyben.vinylManager.interfaces.ChangeListener;
import be.msyben.vinylManager.interfaces.WaitListener;
import be.msyben.vinylManager.properties.Canaux;
import be.msyben.vinylManager.properties.Cotation;
import be.msyben.vinylManager.properties.Language;
import be.msyben.vinylManager.properties.Preferences;
import be.msyben.vinylManager.properties.Support;
import be.msyben.vinylManager.properties.Taille;
import be.msyben.vinylManager.properties.Vitesse;
import be.msyben.vinylManager.tools.FontTool;
import be.msyben.vinylManager.tools.ProxySettings;
import be.msyben.vinylManager.tools.Sort;
import be.msyben.vinylManager.tools.filter.FileFilterVM;
import be.msyben.vinylManager.tools.swing.MyJComboBox;
import be.msyben.vinylManager.tools.Tools;
import be.msyben.vinylManager.tools.WaitThread;
import be.msyben.vinylManager.tools.discogs.DiscogsDownloader;
import be.msyben.vinylManager.tools.discogs.DiscogsSearch;
import be.msyben.vinylManager.tools.filter.FileFilterImport;
import be.msyben.vinylManager.tools.log.VinylManagerLogger;
import be.msyben.vinylManager.tools.swing.MyJList;
import be.msyben.vinylManager.tools.swing.MyMemoryComponent;
import com.toedter.calendar.JDateChooser;
import java.awt.*;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.event.WindowStateListener;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Set;
import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;

/**
 * Fenêtre principale
 *
 * @author Mathieu Syben
 */
public class MainWindow extends JFrame {

    /**
     * uid
     */
    private static final long serialVersionUID = 2l;
    /**
     * Hauteur minimale
     */
    private static final int minHeight = 530;
    /**
     * Largeur minimale
     */
    private static final int minWidth = 750;
    /**
     * dernière largeur
     */
    private int lastWidth = 0;
    /**
     * dernière hauteur
     */
    private int lastHeight = 0;
    /**
     * Le controller
     */
    private Controller controller;
    //MENUBAR
    /**
     * Le menu
     */
    private JMenuBar menuBar = new JMenuBar();
    /**
     * Le menu fichier
     */
    private JMenu fichier = new JMenu();
    /**
     * Le menu action
     */
    private JMenu action = new JMenu();
    /**
     * Le menu aide
     */
    private JMenu aide = new JMenu();
    /**
     * Le sous-menu nouveau
     */
    private JMenuItem nouveau = new JMenuItem();
    /**
     * Le sous-menu ouvrir
     */
    private JMenuItem ouvrir = new JMenuItem();
    /**
     * Le sous-menu recent
     */
    private JMenu recent = new JMenu();
    /**
     * Le sous-menu append
     */
    private JMenuItem append = new JMenuItem();
    /**
     * Le sous-menu importMenu
     */
    private JMenuItem importMenu = new JMenuItem();
    /**
     * Le sous-menu sauver
     */
    private JMenuItem sauver = new JMenuItem();
    /**
     * Le sous-menu sauverSous
     */
    private JMenuItem sauverSous = new JMenuItem();
    /**
     * Le sous-menu exporter
     */
    private JMenuItem exporter = new JMenuItem();
    /**
     * Le sous-menu quitter
     */
    private JMenuItem quitter = new JMenuItem();
    /**
     * Le sous-menu addAlbum
     */
    private JMenuItem addAlbum = new JMenuItem();
    /**
     * Le sous-menu addAlbumDiscogs
     */
    private JMenuItem addAlbumDiscogs = new JMenuItem();
    /**
     * Le sous-menu addDisque
     */
    private JMenuItem addDisque = new JMenuItem();
    /**
     * Le sous-menu editAlbum
     */
    private JMenuItem editAlbum = new JMenuItem();
    /**
     * Le sous-menu editDisque
     */
    private JMenuItem editDisque = new JMenuItem();
    /**
     * Le sous-menu delAlbum
     */
    private JMenuItem delAlbum = new JMenuItem();
    /**
     * Le sous-menu delDisque
     */
    private JMenuItem delDisque = new JMenuItem();
    /**
     * Le sous-menu copyAlbum
     */
    private JMenuItem copyAlbum = new JMenuItem();
    /**
     * Le sous-menu pasteAlbum
     */
    private JMenuItem pasteAlbum = new JMenuItem();
    /**
     * Le sous-menu open discogs
     */
    private JMenuItem openDiscogs = new JMenuItem();
    /**
     * Le sous-menu import discogs
     */
    private JMenuItem importDiscogs = new JMenuItem();
    /**
     * Le sous-menu rechercher
     */
    private JMenuItem rechercher = new JMenuItem();
    /**
     * Le sous-menu preferences
     */
    private JMenuItem preferences = new JMenuItem();
    /**
     * Le sous-menu about
     */
    private JMenuItem about = new JMenuItem();
    private MyMemoryComponent memory = new MyMemoryComponent();
    // ELEMENTS
    /**
     * La liste de gauche
     */
    private AbstractLeftList leftList;
    private AbstractAlbumList albumsList;
    private JLabel disquesLabel = new JLabel();
    private MyJComboBox<Disque> disques = new MyJComboBox<>();
    private JTextField annee = new JTextField();
    private JTextField anneeParution = new JTextField();
    private JTextField artiste = new JTextField();
    private JTextField compositeur = new JTextField();
    private JTextField editeur = new JTextField();
    private JTextField genre = new JTextField();
    private JTextField chef = new JTextField();
    private JTextField orchestre = new JTextField();
    private JTextArea commentaireArea = new JTextArea();
    private JScrollPane commentaire = new JScrollPane(commentaireArea);
    private JTextField etat = new JTextField();
    private JTextField etatDisque = new JTextField();
    private JLabel image = new JLabel();
    private byte[] selectedImage = null;
    private JButton imgPrev = new JButton(Icons.getInstance().leftArrow);
    private JButton imgNext = new JButton(Icons.getInstance().rightArrow);
    private int currentImg = -1;
    private JTextArea musiciensArea = new JTextArea();
    private JScrollPane musiciens = new JScrollPane(musiciensArea);
    private JTextField reference = new JTextField();
    private JTextField titre = new JTextField();
    private JTextField vitesse = new JTextField();
    private JTextField valeur = new JTextField();
    private JTextField couleur = new JTextField();
    private JTextField taille = new JTextField();
    private JTextField support = new JTextField();
    private JDateChooser dateAchat = new JDateChooser(null, Preferences.getInstance().get(Preferences.DATE_FORMAT, "dd/MM/yyyy"));
    private JTextField canaux = new JTextField();
    private JTextField parolier = new JTextField();
    private JTextField location = new JTextField();
    private JTextField pays = new JTextField();
    /**
     * la face A
     */
    private JList<Titre> faceA = new MyJList<>();
    /**
     * la face B
     */
    private JList<Titre> faceB = new MyJList<>();
    /**
     * le panel face A
     */
    private JScrollPane faceAPanel = new JScrollPane(faceA);
    /**
     * le panel face B
     */
    private JScrollPane faceBPanel = new JScrollPane(faceB);
    /**
     * la label des cotes
     */
    private JLabel coteL = new JLabel();
    /**
     * Les labels
     */
    private JLabel artistesLabel = new JLabel();
    private JLabel albumsLabel = new JLabel();
    private JLabel anneeL = new JLabel();
    private JLabel artisteL = new JLabel();
    private JLabel compositeurL = new JLabel();
    private JLabel editeurL = new JLabel();
    private JLabel genreL = new JLabel();
    private JLabel commentaireL = new JLabel();
    private JLabel etatGlobalL = new JLabel();
    private JLabel etatL = new JLabel();
    private JLabel etatDisqueL = new JLabel();
    private JLabel imageL = new JLabel();
    private JLabel chefL = new JLabel();
    private JLabel orchestreL = new JLabel();
    private JLabel musiciensL = new JLabel();
    private JLabel referenceL = new JLabel();
    private JLabel titreL = new JLabel();
    private JLabel vitesseL = new JLabel();
    private JLabel faceALabel = new JLabel();
    private JLabel faceBLabel = new JLabel();
    private JLabel valeurL = new JLabel();
    private JLabel couleurL = new JLabel();
    private JLabel tailleL = new JLabel();
    private JLabel supportL = new JLabel();
    private JLabel dateAchatL = new JLabel();
    private JLabel canauxL = new JLabel();
    private JLabel parolierL = new JLabel();
    private JLabel locationL = new JLabel();
    private JLabel paysL = new JLabel();
    /**
     * les étoiles ;-)
     */
    private JLabel[] cote = new JLabel[5];
    /**
     * Bouton pour trier asc
     */
    private JButton sortArtistAscButton = new JButton(Icons.getInstance().up);
    /**
     * Bouton pour trier desc
     */
    private JButton sortArtistDescButton = new JButton(Icons.getInstance().down);
    /**
     * Singleton
     */
    private static MainWindow _instance = null;
    /**
     * La fenêtre secondaire ouverte
     */
    private Window openWindow = null;
    /**
     * L'état de la fenêtre
     */
    private int state = 0;

    /**
     * getInstance
     *
     * @return une instance
     */
    public static synchronized MainWindow getInstance() {
        if (_instance == null) {
            _instance = new MainWindow();
        }
        return _instance;
    }

    /**
     * getInstance
     *
     * @param toOpen le fichier à ouvrir.
     * @return une instance
     */
    public static synchronized MainWindow getInstance(File toOpen) {
        if (_instance == null) {
            _instance = new MainWindow(toOpen);
        }
        return _instance;
    }

    /**
     * Constructeur.
     */
    private MainWindow() {
        this(null);
    }

    /**
     * Constructeur.
     *
     * @param toOpen le fichier à ouvrir.
     */
    private MainWindow(File toOpen) {
        super(Language.getInstance().get("main.window.title"));

        albumsList = new AlbumList();

        int width = Integer.parseInt(Preferences.getInstance().get(Preferences.MAIN_WINDOW_WIDTH, "910"));
        int height = Integer.parseInt(Preferences.getInstance().get(Preferences.MAIN_WINDOW_HEIGHT, "798"));
        state = Integer.parseInt(Preferences.getInstance().get(Preferences.MAIN_WINDOW_STATE, "0"));

        setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); //On dit à l'application de ne pas se fermer

        setIconImage(Icons.getInstance().icon.getImage());

        Data.getInstance().addChangeListener(new ChangeListener() {
            @Override
            public void onChange() {
                resetFields();
                refresh();
                setFrameTitle();
            }

            @Override
            public void onChange(Album album) {
                resetFields();
                select(album);
                setFrameTitle();
            }

            @Override
            public void onChange(Album album, int disqueIdx) {
                select(album, disqueIdx);
                setFrameTitle();
            }

            @Override
            public void onDelete(Album album) {
                resetFields();
                leftList.updateListAfterDeleteAlbum(album);
                setFrameTitle();
            }

            @Override
            public void refreshCote() {
                setFrameTitle();
                displayCote(albumsList.getCurrentAlbum().getCote(), albumsList.getCurrentAlbum().getCoteDemi());
            }
        });

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

        addWindowListener(new WindowListener() {
            /**
             * Méthode de windowListener
             *
             * @param e l'event
             */
            @Override
            public void windowOpened(WindowEvent e) {
            }

            /**
             * Méthode de windowListener
             *
             * @param e l'event
             */
            @Override
            public void windowClosing(WindowEvent e) {
                quitter();
            }

            /**
             * Méthode de windowListener
             *
             * @param e l'event
             */
            @Override
            public void windowClosed(WindowEvent e) {
            }

            /**
             * Méthode de windowListener
             *
             * @param e l'event
             */
            @Override
            public void windowIconified(WindowEvent e) {
                if (Preferences.getInstance().get(Preferences.MINIMIZE_TO_TRAY, "N").equals("Y")) {
                    if (SystemTray.isSupported()) {

                        final SystemTray tray = SystemTray.getSystemTray();
                        final TrayIcon trayIcon = new TrayIcon(Icons.getInstance().icon.getImage(), Language.getInstance().get("main.window.title"));
                        trayIcon.setImageAutoSize(true);
                        trayIcon.addActionListener(new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                tray.remove(trayIcon);
                                setVisible(true);
                                setExtendedState(Frame.NORMAL);
                                toFront();
                                if (openWindow != null) {
                                    openWindow.setVisible(true);
                                    openWindow.toFront();
                                }
                            }
                        });
                        try {
                            tray.add(trayIcon);
                            setVisible(false);
                            if (openWindow != null) {
                                openWindow.setVisible(false);
                            }
                        } catch (AWTException ex) {
                            VinylManagerLogger.log(ex);
                            System.err.println("TrayIcon could not be added.");
                        }
                    }
                }
            }

            /**
             * Méthode de windowListener
             *
             * @param e l'event
             */
            @Override
            public void windowDeiconified(WindowEvent e) {
            }

            /**
             * Méthode de windowListener
             *
             * @param e l'event
             */
            @Override
            public void windowActivated(WindowEvent e) {

                if (openWindow != null) {
                    openWindow.toFront();
                }
            }

            /**
             * Méthode de windowListener
             *
             * @param e l'event
             */
            @Override
            public void windowDeactivated(WindowEvent e) {
            }
        });

        addWindowStateListener(new WindowStateListener() {
            @Override
            public void windowStateChanged(WindowEvent e) {
                state = e.getNewState();
                Preferences.getInstance().set(Preferences.MAIN_WINDOW_STATE, "" + state);
            }
        });



        putElements();
        putMenu();

        setSize(width, height); //On donne une taille à notre fenêtre
        if (state == MAXIMIZED_BOTH) {
            setExtendedState(JFrame.MAXIMIZED_BOTH);
        }
        setLocationRelativeTo(null); //On centre la fenêtre sur l'ecran
        controller = new Controller();
        if (toOpen == null) {
            controller.lastFileLoad();
        } else {
            try {
                controller.open(toOpen);
            } catch (VinylManagerException ex) {
                VinylManagerLogger.log(ex);
                openWindow = new ErrorWindow(_instance, Language.getInstance().get("error.open.message"), ex);
            }
        }

        setVisible(true);
    }

    /**
     * Met le texte des labels.
     */
    private void setLabelText() {

        artistesLabel.setText(leftList.getTitle());
        albumsLabel.setText(Language.getInstance().get("name.albums"));
        anneeL.setText(Language.getInstance().get("name.annee"));
        artisteL.setText(Language.getInstance().get("name.artiste"));
        editeurL.setText(Language.getInstance().get("name.editeur"));
        genreL.setText(Language.getInstance().get("name.genre"));
        commentaireL.setText(Language.getInstance().get("name.commentaire"));
        etatGlobalL.setText(Language.getInstance().get("name.etat"));
        etatL.setText(Language.getInstance().get("name.etat.pochette"));
        etatDisqueL.setText(Language.getInstance().get("name.etat.disque"));
        imageL.setText(Language.getInstance().get("name.image"));
        musiciensL.setText(Language.getInstance().get("name.musiciens"));
        referenceL.setText(Language.getInstance().get("name.reference"));
        titreL.setText(Language.getInstance().get("name.titre"));
        vitesseL.setText(Language.getInstance().get("name.vitesse"));
        faceALabel.setText(Language.getInstance().get("name.faceA"));
        faceBLabel.setText(Language.getInstance().get("name.faceB"));
        valeurL.setText(Language.getInstance().get("name.valeur"));
        couleurL.setText(Language.getInstance().get("name.couleur"));
        tailleL.setText(Language.getInstance().get("name.taille"));
        canauxL.setText(Language.getInstance().get("name.canaux"));
        parolierL.setText(Language.getInstance().get("name.parolier"));
        locationL.setText(Language.getInstance().get("name.location"));
        paysL.setText(Language.getInstance().get("name.pays"));
        coteL.setText(Language.getInstance().get("name.cote"));
        disquesLabel.setText(Language.getInstance().get("name.disque"));
        chefL.setText(Language.getInstance().get("name.chef"));
        orchestreL.setText(Language.getInstance().get("name.orchestre"));
        compositeurL.setText(Language.getInstance().get("name.compositeur.short"));
        compositeurL.setToolTipText(Language.getInstance().get("name.compositeur.full"));
        supportL.setText(Language.getInstance().get("name.support"));
        dateAchatL.setText(Language.getInstance().get("name.date.achat"));

        // menus
        fichier.setText(Language.getInstance().get("main.menu.fichier"));
        action.setText(Language.getInstance().get("main.menu.action"));
        aide.setText(Language.getInstance().get("main.menu.aide"));
        nouveau.setText(Language.getInstance().get("main.menu.fichier.nouveau"));
        ouvrir.setText(Language.getInstance().get("main.menu.fichier.ouvrir"));
        recent.setText(Language.getInstance().get("main.menu.fichier.recent"));
        append.setText(Language.getInstance().get("main.menu.fichier.append"));
        importMenu.setText(Language.getInstance().get("main.menu.fichier.import"));
        sauver.setText(Language.getInstance().get("main.menu.fichier.sauver"));
        sauverSous.setText(Language.getInstance().get("main.menu.fichier.sauver.sous"));
        exporter.setText(Language.getInstance().get("main.menu.fichier.exporter"));
        quitter.setText(Language.getInstance().get("main.menu.fichier.quitter"));
        addAlbum.setText(Language.getInstance().get("main.menu.action.ajouter.album"));
        addAlbumDiscogs.setText(Language.getInstance().get("main.menu.action.ajouter.album.discogs"));
        addDisque.setText(Language.getInstance().get("main.menu.action.ajouter.disque"));
        editAlbum.setText(Language.getInstance().get("main.menu.action.editer.album"));
        editDisque.setText(Language.getInstance().get("main.menu.action.editer.disque"));
        delAlbum.setText(Language.getInstance().get("main.menu.action.supprimer.album"));
        delDisque.setText(Language.getInstance().get("main.menu.action.supprimer.disque"));
        rechercher.setText(Language.getInstance().get("main.menu.action.rechercher"));
        copyAlbum.setText(Language.getInstance().get("main.menu.action.copy"));
        pasteAlbum.setText(Language.getInstance().get("main.menu.action.paste"));
        openDiscogs.setText(Language.getInstance().get("main.menu.action.open.discogs"));
        importDiscogs.setText(Language.getInstance().get("main.menu.action.import.discogs"));
        preferences.setText(Language.getInstance().get("main.menu.action.preferences"));
        about.setText(Language.getInstance().get("main.menu.aide.about"));
        AideMenuItem.updateName();
    }

    /**
     * place les éléments dans la fenêtre
     */
    private void placeElements() {
        int width = getWidth();
        int height = getHeight();

        boolean showIcons = false;
        int iconsHeight = 32;

        if (state != Frame.MAXIMIZED_BOTH) {

            // La taille max est celle effective de l'écran
            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
            GraphicsConfiguration gconf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
            Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(gconf);
            int maxWidth = (int) screenSize.getWidth() - insets.left - insets.right;
            int maxHeight = (int) screenSize.getHeight() - insets.bottom - insets.top;
            //indique si on doit faire un redimensionnement ou pas.
            boolean resize = false;
            if (width < minWidth) {
                width = minWidth;
                resize = true;
            }
            if (height < minHeight) {
                height = minHeight;
                resize = true;
            }

            if (width > maxWidth) {
                setLocation(insets.left, getLocation().y);
                width = maxWidth;
                resize = true;
            }

            if (height > maxHeight) {
                setLocation(getLocation().x, insets.right);
                height = maxHeight;
                resize = true;
            }

            if (resize) {
                setSize(width, height);
            }

        }

        if (width == lastWidth && height == lastHeight) {
            return;
        } else {
            lastWidth = width;
            lastHeight = height;
        }

        Preferences.getInstance().set(Preferences.MAIN_WINDOW_WIDTH, "" + width);
        Preferences.getInstance().set(Preferences.MAIN_WINDOW_HEIGHT, "" + height);

        // Je garde 15 entre chaque "tiers", 5 à gauche et 5 à droite
        int tiers = (width - 50) / 3;

        // MENU
        int startHeightPanel = 30;
        if (showIcons) {
            startHeightPanel += iconsHeight;
        }


        // TIERS 1
        artistesLabel.setBounds(5, startHeightPanel, tiers - 50, 20);
        leftList.getComponent().setBounds(5, startHeightPanel + 20, tiers, height - 90);


        sortArtistDescButton.setBounds(tiers - 23, startHeightPanel + 5, 15, 15);
        sortArtistAscButton.setBounds(tiers - 40, startHeightPanel + 5, 15, 15);

        //TIERS 2
        int littleFieldWidth = (tiers - 125) / 2;
        int labelWidth = 60;
        int bigFieldWidth = littleFieldWidth + littleFieldWidth + labelWidth + 5;

        int debut = tiers + 20;
        int debut2 = debut + labelWidth;
        int debut3 = debut2 + 5 + littleFieldWidth;
        int debut4 = debut3 + labelWidth;
        int labelHeight = 15;
        int fieldHeight = 25;
        int commentaireHeight = 95;

        int dejaUtilise = 8 * (5 + fieldHeight) + commentaireHeight + (5 + labelHeight) + 120;
        if (showIcons) {
            dejaUtilise += iconsHeight;
        }
        int reste = height - dejaUtilise;

        int albumPanelHeight = 0;
        int facePanelHeight = 0;
        if (reste > 430) {
            albumPanelHeight = reste - 200;
            facePanelHeight = 200;
        } else {
            albumPanelHeight = reste / 2 + 30;
            facePanelHeight = reste / 2 - 30;
        }


        int h = startHeightPanel;
        albumsLabel.setBounds(debut, h, tiers, labelHeight);
        h += labelHeight + 5;
        albumsList.getComponent().setBounds(debut, h, tiers, albumPanelHeight);
        h += albumPanelHeight + 5;
        artisteL.setBounds(debut, h + 5, labelWidth, labelHeight);
        artiste.setBounds(debut2, h, bigFieldWidth, fieldHeight);
        h += fieldHeight + 5;

        titreL.setBounds(debut, h + 5, labelWidth, labelHeight);
        titre.setBounds(debut2, h, bigFieldWidth, fieldHeight);
        h += fieldHeight + 5;

        compositeurL.setBounds(debut, h + 5, labelWidth, labelHeight);
        compositeur.setBounds(debut2, h, bigFieldWidth, fieldHeight);
        h += fieldHeight + 5;

        editeurL.setBounds(debut, h + 5, labelWidth, labelHeight);
        editeur.setBounds(debut2, h, bigFieldWidth, fieldHeight);
        h += fieldHeight + 5;

        paysL.setBounds(debut, h + 5, labelWidth, labelHeight);
        pays.setBounds(debut2, h, littleFieldWidth, fieldHeight);
        genreL.setBounds(debut3, h + 5, labelWidth, labelHeight);
        genre.setBounds(debut4, h, littleFieldWidth, fieldHeight);
        h += fieldHeight + 5;

        anneeL.setBounds(debut, h + 5, labelWidth, labelHeight);
        annee.setBounds(debut2, h, littleFieldWidth/2-5, fieldHeight);
        anneeParution.setBounds(debut2+littleFieldWidth/2, h, littleFieldWidth/2-5, fieldHeight);
        anneeParution.setToolTipText(Language.getInstance().get("name.annee.parution"));
        referenceL.setBounds(debut3, h + 5, labelWidth, labelHeight);
        reference.setBounds(debut4, h, littleFieldWidth, fieldHeight);
        h += fieldHeight + 5;


        chefL.setBounds(debut, h + 5, labelWidth, labelHeight);
        chef.setBounds(debut2, h, bigFieldWidth, fieldHeight);
        h += fieldHeight + 5;

        orchestreL.setBounds(debut, h + 5, labelWidth, labelHeight);
        orchestre.setBounds(debut2, h, bigFieldWidth, fieldHeight);
        h += fieldHeight + 5;

        commentaireL.setBounds(debut, h, tiers, labelHeight);
        h += labelHeight + 5;
        commentaire.setBounds(debut, h, tiers, commentaireHeight);
        h += commentaireHeight + 5;

        int startFace = h;
        faceALabel.setBounds(debut, h, tiers, labelHeight);
        h += labelHeight + 5;
        faceAPanel.setBounds(debut, h, tiers, facePanelHeight);
        faceA.setSize(tiers, facePanelHeight);

        //TIERS 3
        debut = tiers + tiers + 30;
        debut2 = debut + labelWidth;
        debut3 = debut2 + 5 + littleFieldWidth;
        debut4 = debut3 + labelWidth;

        int starHeight = 25;

        h = startHeightPanel;
        disquesLabel.setBounds(debut, h + 5, 70, labelHeight);
        disques.setBounds(debut + 70, h, Math.min(tiers - 70, 185), fieldHeight);
        
        menuBar.setBounds(0, 0, debut + 70, 25);
        memory.setBounds(debut + 70, 0, Math.min(tiers - 70, 185), 25);
        
        disques.setSize(Math.min(tiers - 70, 185), fieldHeight);
        for (Component c : disques.getComponents()) {
            if (c instanceof JButton) {
                c.setBounds(Math.min(tiers - 70, 185) - 20, 0, 20, fieldHeight);
            }
        }

        h += fieldHeight + 5;

        imageL.setBounds(debut, h, 50, labelHeight);

        if (tiers >= 285) {
            imageL.setVisible(true);
            image.setBounds(debut + 55, h, 200, 200);
            imgPrev.setBounds(debut + 20, h + 85, 30, 30);
            imgNext.setBounds(debut + 260, h + 85, 30, 30);
        } else {
            imageL.setVisible(false);

            int finDL = debut + 70 + Math.min(tiers - 70, 185);
            int debutImageNeeded = finDL - 200;
            if (debutImageNeeded < (debut + 40)) {
                debutImageNeeded = debut + 40;
            }

            image.setBounds(debutImageNeeded, h, 200, 200);

            imgPrev.setBounds(debut + 5, h + 60, 30, 30);
            imgNext.setBounds(debut + 5, h + 110, 30, 30);

        }
        h += 210;

        coteL.setBounds(debut, h + 5, 50, labelHeight);
        int espaceEtoile = Math.min((tiers - 50) / 5, 35);
        for (int i = 0; i < cote.length; i++) {

            cote[i].setBounds(debut + 50 + (espaceEtoile * i), h, starHeight, starHeight);
        }
        h += starHeight + 11;

        etatL.setBounds(debut, h + 5, labelWidth, labelHeight);
        etat.setBounds(debut2, h, littleFieldWidth, fieldHeight);
        etatDisqueL.setBounds(debut3, h + 5, labelWidth, labelHeight);
        etatDisque.setBounds(debut4, h, littleFieldWidth, fieldHeight);
        h += fieldHeight + 5;


        tailleL.setBounds(debut, h + 5, labelWidth, labelHeight);
        taille.setBounds(debut2, h, littleFieldWidth, fieldHeight);
        vitesseL.setBounds(debut3, h + 5, labelWidth, labelHeight);
        vitesse.setBounds(debut4, h, littleFieldWidth, fieldHeight);
        h += fieldHeight + 5;


        canauxL.setBounds(debut, h + 5, labelWidth, labelHeight);
        canaux.setBounds(debut2, h, littleFieldWidth, fieldHeight);
        couleurL.setBounds(debut3, h + 5, labelWidth, labelHeight);
        couleur.setBounds(debut4, h, littleFieldWidth, fieldHeight);
        h += fieldHeight + 5;


        supportL.setBounds(debut, h + 5, labelWidth, labelHeight);
        support.setBounds(debut2, h, littleFieldWidth, fieldHeight);
        valeurL.setBounds(debut3, h + 5, labelWidth, labelHeight);
        valeur.setBounds(debut4, h, littleFieldWidth, fieldHeight);
        h += fieldHeight + 5;


        dateAchatL.setBounds(debut, h + 5, labelWidth, labelHeight);
        dateAchat.setBounds(debut2, h, littleFieldWidth, fieldHeight);
        parolierL.setBounds(debut3, h + 5, labelWidth, labelHeight);
        parolier.setBounds(debut4, h, littleFieldWidth, fieldHeight);
        h += fieldHeight + 5;
        
        locationL.setBounds(debut, h + 5, labelWidth, labelHeight);
        location.setBounds(debut2, h, bigFieldWidth, fieldHeight);
        h += fieldHeight + 5;


        musiciensL.setBounds(debut, h, 200, labelHeight);
        h += labelHeight + 5;
        musiciens.setBounds(debut, h, tiers, startFace - h - 5);

        h += startFace - h - 5;

        h = startFace;
        faceBLabel.setBounds(debut, h, tiers, labelHeight);
        h += labelHeight + 5;
        faceBPanel.setBounds(debut, h, tiers, facePanelHeight);
        faceB.setSize(tiers, facePanelHeight);

        this.getContentPane().repaint();
        this.getContentPane().validate();
    }

    /**
     * Change le titre de la fenêtre
     */
    private void setFrameTitle() {
        setTitle(controller.getFrameTitle());
    }

    /**
     * Ajoute le menu à la fenêtre
     */
    private void putMenu() {
        Container c = getContentPane();
        c.setLayout(null);
        c.setSize(getWidth(), getHeight());

        c.add(menuBar);
        c.add(memory);
        memory.run();
        menuBar.add(fichier);
        menuBar.add(action);
        fichier.add(nouveau);
        fichier.addSeparator();
        fichier.add(ouvrir);
        fichier.add(recent);
        fichier.add(append);
        fichier.add(sauver);
        fichier.add(sauverSous);
        fichier.addSeparator();
        fichier.add(importMenu);
        fichier.add(exporter);
        fichier.addSeparator();
        fichier.add(quitter);
        menuBar.add(action);
        action.add(addAlbum);
        action.add(addAlbumDiscogs);
        action.add(addDisque);
        action.addSeparator();
        action.add(editAlbum);
        action.add(editDisque);
        action.addSeparator();
        action.add(delAlbum);
        action.add(delDisque);
        action.addSeparator();
        action.add(copyAlbum);
        action.add(pasteAlbum);
        action.addSeparator();
        action.add(openDiscogs);
        action.add(importDiscogs);        
        action.addSeparator();
        action.add(rechercher);
        action.addSeparator();
        action.add(preferences);
        menuBar.add(aide);
        try {
            aide.add(AideMenuItem.getAideMenuItem());
            aide.addSeparator();
        } catch (VinylManagerException ex) {
            VinylManagerLogger.log(ex);
            openWindow = new ErrorWindow(_instance, Language.getInstance().get("error.creation.aide"), ex);
        }
        aide.add(about);


        action.addMenuListener(new MenuListener() {
            @Override
            public void menuSelected(MenuEvent e) {
                if (albumsList.getCurrentAlbum() != null) {
                    editAlbum.setEnabled(true);
                    delAlbum.setEnabled(true);
                    copyAlbum.setEnabled(true);
                    addDisque.setEnabled(true);
                    openDiscogs.setEnabled(albumsList.getCurrentAlbum().getDiscogsId() != null && !albumsList.getCurrentAlbum().getDiscogsId().isEmpty());
                } else {
                    editAlbum.setEnabled(false);
                    delAlbum.setEnabled(false);
                    copyAlbum.setEnabled(false);
                    addDisque.setEnabled(false);
                    openDiscogs.setEnabled(false);
                }
                if (albumsList.getCurrentAlbum() != null && disques.getSelectedIndex() >= 0) {
                    editDisque.setEnabled(true);
                    delDisque.setEnabled(true);
                } else {
                    editDisque.setEnabled(false);
                    delDisque.setEnabled(false);
                }

                pasteAlbum.setEnabled(Toolkit.getDefaultToolkit().getSystemClipboard().isDataFlavorAvailable(Album.ALBUM_FLAVOR));
            }

            @Override
            public void menuDeselected(MenuEvent e) {
            }

            @Override
            public void menuCanceled(MenuEvent e) {
            }
        });


        nouveau.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_N, ActionEvent.CTRL_MASK));
        sauver.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_S, ActionEvent.CTRL_MASK));
        ouvrir.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_O, ActionEvent.CTRL_MASK));
        quitter.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_F4, ActionEvent.ALT_MASK));
        sauverSous.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F12, 0));
        addAlbum.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_I, ActionEvent.CTRL_MASK));
        addAlbumDiscogs.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_I, ActionEvent.CTRL_MASK + ActionEvent.SHIFT_MASK));
        addDisque.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_D, ActionEvent.CTRL_MASK));
        editAlbum.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_I, ActionEvent.ALT_MASK));
        editDisque.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_D, ActionEvent.ALT_MASK));
        delAlbum.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_I, ActionEvent.ALT_MASK + ActionEvent.CTRL_MASK));
        delDisque.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_D, ActionEvent.ALT_MASK + ActionEvent.CTRL_MASK));
        rechercher.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_F, ActionEvent.CTRL_MASK));


        copyAlbum.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_C, ActionEvent.SHIFT_MASK + ActionEvent.CTRL_MASK));
        pasteAlbum.setAccelerator(KeyStroke.getKeyStroke(
                KeyEvent.VK_V, ActionEvent.SHIFT_MASK + ActionEvent.CTRL_MASK));

        nouveau.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (controller.isModified()) {
                    int result = JOptionPane.showConfirmDialog(_instance, Language.getInstance().get("confirm.save.dialog"), Language.getInstance().get("confirm.save.title"), JOptionPane.YES_NO_CANCEL_OPTION);
                    switch (result) {
                        case JOptionPane.YES_OPTION:
                            sauver();
                            nouveau();
                            break;
                        case JOptionPane.NO_OPTION:
                            nouveau();
                            break;
                        case JOptionPane.CANCEL_OPTION:
                            break;
                    }
                } else {
                    nouveau();
                }
            }
        });
        ouvrir.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (controller.isModified()) {
                    int result = JOptionPane.showConfirmDialog(_instance, Language.getInstance().get("confirm.save.dialog"), Language.getInstance().get("confirm.save.title"), JOptionPane.YES_NO_CANCEL_OPTION);
                    switch (result) {
                        case JOptionPane.YES_OPTION:
                            sauver();
                            open();
                            break;
                        case JOptionPane.NO_OPTION:
                            open();
                            break;
                        case JOptionPane.CANCEL_OPTION:
                            break;
                    }

                } else {
                    open();
                }
            }
        });

        recent.addMenuListener(new MenuListener() {
            @Override
            public void menuSelected(MenuEvent e) {
                recent.removeAll();
                List<String> recents = controller.getLastOpenedFiles();
                for (final String s : recents) {
                    JMenuItem recentItem = new JMenuItem(s);
                    recentItem.addActionListener(new ActionListener() {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            if (controller.isModified()) {
                                int result = JOptionPane.showConfirmDialog(_instance, Language.getInstance().get("confirm.save.dialog"), Language.getInstance().get("confirm.save.title"), JOptionPane.YES_NO_CANCEL_OPTION);
                                switch (result) {
                                    case JOptionPane.YES_OPTION:
                                        sauver();
                                        openFile(s);
                                        break;
                                    case JOptionPane.NO_OPTION:
                                        openFile(s);
                                        break;
                                    case JOptionPane.CANCEL_OPTION:
                                        break;
                                }

                            } else {
                                openFile(s);
                            }
                        }
                    });
                    recent.add(recentItem);
                }
            }

            @Override
            public void menuDeselected(MenuEvent e) {
            }

            @Override
            public void menuCanceled(MenuEvent e) {
            }
        });

        importMenu.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (controller.isModified()) {
                    int result = JOptionPane.showConfirmDialog(_instance, Language.getInstance().get("confirm.save.dialog"), Language.getInstance().get("confirm.save.title"), JOptionPane.YES_NO_CANCEL_OPTION);
                    switch (result) {
                        case JOptionPane.YES_OPTION:
                            sauver();
                            importCollection();
                            break;
                        case JOptionPane.NO_OPTION:
                            importCollection();
                            break;
                        case JOptionPane.CANCEL_OPTION:
                            break;
                    }

                } else {
                    importCollection();
                }
            }
        });


        append.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                append();
            }
        });

        sauver.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                sauverWithWaitPanel();
            }
        });
        sauverSous.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                sauverSousWithWaitPanel();
            }
        });
        quitter.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                quitter();
            }
        });
        addAlbum.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                openWindow = new AlbumWindow(controller);
            }
        });
        addAlbumDiscogs.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                openWindow = new DiscogsSearchWindow(controller);
            }
        });
        addDisque.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (albumsList.getCurrentAlbum() != null) {
                    openWindow = new DisqueWindow(controller, albumsList.getCurrentAlbum());
                } else {
                    openWindow = new ErrorWindow(_instance, Language.getInstance().get("error.choice.album"));
                }
            }
        });
        editAlbum.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (albumsList.getCurrentAlbum() != null) {
                    openWindow = new AlbumWindow(controller, albumsList.getCurrentAlbum());
                } else {
                    openWindow = new ErrorWindow(_instance, Language.getInstance().get("error.choice.album"));
                }
            }
        });
        editDisque.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (albumsList.getCurrentAlbum() != null && disques.getSelectedIndex() >= 0) {
                    openWindow = new DisqueWindow(controller, (Disque) disques.getSelectedItem(), albumsList.getCurrentAlbum());
                } else {
                    openWindow = new ErrorWindow(_instance, Language.getInstance().get("error.choice.disque"));
                }
            }
        });
        delAlbum.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (albumsList.getCurrentAlbum() != null) {

                    int result = JOptionPane.showConfirmDialog(_instance, Language.getInstance().get("confirm.del.album.dialog"), Language.getInstance().get("confirm.del.album.title"), JOptionPane.YES_NO_OPTION);
                    if (result == JOptionPane.YES_OPTION) {
                        try {
                            controller.deleteAlbum(albumsList.getCurrentAlbum());
                        } catch (VinylManagerException ex) {
                            VinylManagerLogger.log(ex);
                            openWindow = new ErrorWindow(_instance, ex.getMessage());
                        }
                    }
                } else {
                    openWindow = new ErrorWindow(_instance, Language.getInstance().get("error.choice.album"));
                }
            }
        });
        delDisque.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (albumsList.getCurrentAlbum() != null && disques.getSelectedItem() != null) {

                    int result = JOptionPane.showConfirmDialog(_instance, Language.getInstance().get("confirm.del.disque.dialog"), Language.getInstance().get("confirm.del.disque.title"), JOptionPane.YES_NO_OPTION);
                    if (result == JOptionPane.YES_OPTION) {
                        try {
                            controller.deleteDisque(albumsList.getCurrentAlbum(), (Disque) disques.getSelectedItem());
                        } catch (VinylManagerException ex) {
                            VinylManagerLogger.log(ex);
                            openWindow = new ErrorWindow(_instance, ex.getMessage());
                        }
                    }

                } else {
                    openWindow = new ErrorWindow(_instance, Language.getInstance().get("error.choice.disque"));
                }
            }
        });
        openDiscogs.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (albumsList.getCurrentAlbum() != null) {
                    String url = DiscogsDownloader.DISCOGS_URL+"/release/"+albumsList.getCurrentAlbum().getDiscogsId();
                    if (Desktop.isDesktopSupported()) {
                        try {
                            Desktop.getDesktop().browse(new URI(url));
                        } catch (URISyntaxException | IOException ex) {
                            openWindow = new ErrorWindow(_instance, Language.getInstance().get("error.opening.album.disogs"), ex);
                        }
                    } else {
                            openWindow = new ErrorWindow(_instance, Language.getInstance().get("error.opening.album.disogs"));
                    }
                } else {
                    openWindow = new ErrorWindow(_instance, Language.getInstance().get("error.choice.album"));
                }
            }
        });
        importDiscogs.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                importDiscogs();
            }
        });
        about.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                openWindow = new About();
            }
        });
        exporter.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                //choixFichierExport();
                openWindow = new ExportWindow(controller);
            }
        });
        rechercher.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                openWindow = new SearchWindow();
            }
        });
        preferences.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                openWindow = new PrefWindow();
            }
        });

        copyAlbum.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (albumsList.getCurrentAlbum() != null) {
                    Toolkit.getDefaultToolkit().getSystemClipboard().setContents(albumsList.getCurrentAlbum(), null);
                } else {
                    openWindow = new ErrorWindow(_instance, Language.getInstance().get("error.choice.album"));
                }
            }
        });

        pasteAlbum.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    Transferable t = Toolkit.getDefaultToolkit().getSystemClipboard().getContents(null);
                    if (t.isDataFlavorSupported(Album.ALBUM_FLAVOR)) {
                        Object pasted = t.getTransferData(Album.ALBUM_FLAVOR);
                        if (pasted instanceof Album) {
                            Album pastedAlbum = (Album) pasted;
                            controller.addAlbum(pastedAlbum);
                        } else {
                            openWindow = new ErrorWindow(_instance, Language.getInstance().get("error.paste.not.album.clipboard"));
                        }
                    } else {
                        openWindow = new ErrorWindow(_instance, Language.getInstance().get("error.paste.not.album.clipboard"));
                    }

                } catch (UnsupportedFlavorException | IOException | VinylManagerException ex) {
                    openWindow = new ErrorWindow(_instance, Language.getInstance().get("error.paste.album"));
                }
            }
        });
    }

    /**
     * Rafraichi l'affichage.
     */
    private void refresh() {
        Album selected = albumsList.getCurrentAlbum();
        int disque = disques.getSelectedIndex();

        leftList.updateList(selected);
        albumsList.select(selected);
        if (disque >= 0) {
            disques.setSelectedIndex(disque);
        }

    }

    /**
     * Sélection d'un album.
     *
     * @param album l'album sélectionné.
     */
    private void select(Album album) {
        leftList.updateList(album);
        albumsList.select(album);
    }

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

        Container c = getContentPane();

        c.add(artistesLabel);
        makeLeftList();
        this.getContentPane().add(leftList.getComponent());

        c.add(albumsLabel);
        albumsList.addListListener(new AlbumListListener() {
            @Override
            public void selection() {
                showAlbum();
            }

            @Override
            public void doubleClic() {
                if (albumsList.getCurrentAlbum() != null) {
                    openWindow = new AlbumWindow(controller, albumsList.getCurrentAlbum());
                } else {
                    openWindow = new ErrorWindow(_instance, Language.getInstance().get("error.choice.album"));
                }
            }
        });
        c.add(albumsList.getComponent());

        c.add(artisteL);
        artiste.setEditable(false);
        c.add(artiste);

        c.add(compositeurL);
        compositeur.setEditable(false);
        c.add(compositeur);

        c.add(titreL);
        titre.setEditable(false);
        c.add(titre);

        c.add(editeurL);
        editeur.setEditable(false);
        c.add(editeur);

        c.add(paysL);
        pays.setEditable(false);
        c.add(pays);

        c.add(genreL);
        genre.setEditable(false);
        c.add(genre);

        c.add(anneeL);
        annee.setEditable(false);
        c.add(annee);
        anneeParution.setEditable(false);
        c.add(anneeParution);

        c.add(referenceL);
        reference.setEditable(false);
        c.add(reference);

        //c.add(etatGlobalL);
        c.add(etatL);
        etat.setEditable(false);
        c.add(etat);

        c.add(etatDisqueL);
        etatDisque.setEditable(false);
        c.add(etatDisque);

        c.add(supportL);
        support.setEditable(false);
        c.add(support);

        c.add(valeurL);
        valeur.setEditable(false);
        c.add(valeur);

        c.add(vitesseL);
        vitesse.setEditable(false);
        c.add(vitesse);

        c.add(tailleL);
        taille.setEditable(false);
        c.add(taille);

        c.add(canauxL);
        canaux.setEditable(false);
        c.add(canaux);

        c.add(parolierL);
        parolier.setEditable(false);
        c.add(parolier);

        c.add(locationL);
        location.setEditable(false);
        c.add(location);

        c.add(commentaireL);
        commentaireArea.setEditable(false);
        commentaireArea.setBackground(titre.getBackground());
        commentaireArea.setBorder(titre.getBorder());
        commentaire.setBorder(null);
        c.add(commentaire);

        c.add(disquesLabel);
        disques.removeAllItems();
        disques.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                showDisque();
            }
        });
        c.add(disques);

        c.add(imageL);
        c.add(image);
        image.setBorder(new LineBorder(Color.BLACK, 1));
        image.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (image.getIcon() != null && image.isEnabled() && selectedImage != null) {
                    if (SwingUtilities.isLeftMouseButton(e)) {
                        new ZoomImage(selectedImage);
                    } else if (SwingUtilities.isRightMouseButton(e)) {
                        final JPopupMenu popup = new JPopupMenu();
                        JMenuItem copy = new JMenuItem(Language.getInstance().get("name.copy"));
                        copy.addActionListener(new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                Tools.setClipboard(new ImageIcon(selectedImage));
                                popup.setVisible(false);
                            }
                        });
                        copy.setEnabled(true);
                        popup.add(copy);
                        popup.setVisible(true);
                        popup.show(e.getComponent(), e.getX(), e.getY());
                    }
                }
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                if (image.getIcon() != null && image.isEnabled()) {
                    setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
                }
            }

            @Override
            public void mouseExited(MouseEvent e) {
                setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
            }
        });

        imgNext.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                currentImg++;
                try {
                    displayImage();
                } catch (VinylManagerException ex) {
                }
            }
        });
        c.add(imgNext);
        imgPrev.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                currentImg--;
                try {
                    displayImage();
                } catch (VinylManagerException ex) {
                }
            }
        });
        c.add(imgPrev);
        try {
            displayImage();
        } catch (VinylManagerException ex) {
        }

        c.add(chefL);
        chef.setEditable(false);
        c.add(chef);

        c.add(orchestreL);
        orchestre.setEditable(false);
        c.add(orchestre);

        c.add(musiciensL);
        musiciensArea.setEditable(false);
        musiciensArea.setBackground(titre.getBackground());
        musiciensArea.setBorder(titre.getBorder());
        musiciens.setBorder(null);
        c.add(musiciens);

        c.add(dateAchatL);
        c.add(dateAchat);
        dateAchat.remove(dateAchat.getCalendarButton());
        dateAchat.setFont(FontTool.font2);
        dateAchat.setToolTipText(null);
        ((JTextField) dateAchat.getDateEditor().getUiComponent()).setEditable(false);


        c.add(faceALabel);
        c.add(faceAPanel);
        faceA.setEnabled(true);
        faceA.addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                if (!faceA.isSelectionEmpty()) {
                    faceB.clearSelection();
                }
            }
        });
        faceA.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (SwingUtilities.isRightMouseButton(e)) {
                    int index = faceA.locationToIndex(e.getPoint());
                    if (index <= faceA.getModel().getSize()) {
                        final Titre t = (Titre) faceA.getModel().getElementAt(index);
                        faceA.setSelectedIndex(index);
                        final JPopupMenu popup = new JPopupMenu();
                        JMenuItem lyrics = new JMenuItem(Language.getInstance().get("search.lyrics.edit").replace("%1", t.getNom()));
                        lyrics.addActionListener(new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                new LyricsWindow(controller, (Disque) disques.getSelectedItem(), albumsList.getCurrentAlbum(), t);
                                popup.setVisible(false);
                            }
                        });
                        popup.add(lyrics);

                        if (t.getLinkedFilePath() != null) {
                            JMenuItem removeLinked = new JMenuItem(Language.getInstance().get("linked.file.del").replace("%1", t.getNom()));
                            removeLinked.addActionListener(new ActionListener() {
                                @Override
                                public void actionPerformed(ActionEvent e) {
                                    t.setLinkedFilePath(null);
                                    controller.setModified();
                                }
                            });

                            JMenuItem openLinked = new JMenuItem(Language.getInstance().get("linked.file.open").replace("%1", t.getNom()));
                            openLinked.addActionListener(new ActionListener() {
                                @Override
                                public void actionPerformed(ActionEvent e) {
                                    try {
                                        Tools.openFile(t.getLinkedFilePath());
                                    } catch (VinylManagerException ex) {
                                        VinylManagerLogger.log(ex);
                                        new ErrorWindow(MainWindow.this, ex.getMessage(), ex);
                                    }
                                }
                            });
                            popup.add(openLinked);
                            popup.add(removeLinked);
                        } else {
                            JMenuItem addLinked = new JMenuItem(Language.getInstance().get("linked.file.add").replace("%1", t.getNom()));
                            addLinked.addActionListener(new ActionListener() {
                                @Override
                                public void actionPerformed(ActionEvent e) {
                                    addFileToTitre(t);
                                    controller.setModified();
                                }
                            });
                            popup.add(addLinked);
                        }

                        popup.setVisible(true);
                        popup.show(e.getComponent(), e.getX(), e.getY());
                    }
                } else {
                    if (e.getClickCount() == 2) {
                        int index = faceA.locationToIndex(e.getPoint());
                        if (index <= faceA.getModel().getSize()) {
                            final Titre t = (Titre) faceA.getModel().getElementAt(index);
                            if (t != null && t.getLinkedFilePath() != null) {
                                try {
                                    Tools.openFile(t.getLinkedFilePath());
                                } catch (VinylManagerException ex) {
                                    VinylManagerLogger.log(ex);
                                    new ErrorWindow(MainWindow.this, ex.getMessage(), ex);
                                }
                            }
                        }
                    }
                }
            }
        });

        c.add(faceBLabel);
        c.add(faceBPanel);
        faceB.setEnabled(true);
        faceB.addListSelectionListener(new ListSelectionListener() {
            @Override
            public void valueChanged(ListSelectionEvent e) {
                if (!faceB.isSelectionEmpty()) {
                    faceA.clearSelection();
                }
            }
        });
        faceB.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (SwingUtilities.isRightMouseButton(e)) {
                    int index = faceB.locationToIndex(e.getPoint());
                    if (index <= faceB.getModel().getSize()) {
                        faceB.setSelectedIndex(index);
                        final Titre t = (Titre) faceB.getModel().getElementAt(index);
                        final JPopupMenu popup = new JPopupMenu();
                        JMenuItem lyrics = new JMenuItem(Language.getInstance().get("search.lyrics.edit").replace("%1", t.getNom()));
                        lyrics.addActionListener(new ActionListener() {
                            @Override
                            public void actionPerformed(ActionEvent e) {
                                new LyricsWindow(controller, (Disque) disques.getSelectedItem(), albumsList.getCurrentAlbum(), t);
                                popup.setVisible(false);
                            }
                        });
                        popup.add(lyrics);

                        if (t.getLinkedFilePath() != null) {
                            JMenuItem removeLinked = new JMenuItem(Language.getInstance().get("linked.file.del").replace("%1", t.getNom()));
                            removeLinked.addActionListener(new ActionListener() {
                                @Override
                                public void actionPerformed(ActionEvent e) {
                                    t.setLinkedFilePath(null);
                                    controller.setModified();
                                }
                            });
                            popup.add(removeLinked);
                            JMenuItem openLinked = new JMenuItem(Language.getInstance().get("linked.file.open").replace("%1", t.getNom()));
                            openLinked.addActionListener(new ActionListener() {
                                @Override
                                public void actionPerformed(ActionEvent e) {
                                    try {
                                        Tools.openFile(t.getLinkedFilePath());
                                    } catch (VinylManagerException ex) {
                                        VinylManagerLogger.log(ex);
                                        new ErrorWindow(MainWindow.this, ex.getMessage(), ex);
                                    }
                                }
                            });
                            popup.add(openLinked);
                        } else {
                            JMenuItem addLinked = new JMenuItem(Language.getInstance().get("linked.file.add").replace("%1", t.getNom()));
                            addLinked.addActionListener(new ActionListener() {
                                @Override
                                public void actionPerformed(ActionEvent e) {
                                    addFileToTitre(t);
                                    controller.setModified();
                                }
                            });
                            popup.add(addLinked);
                        }

                        popup.setVisible(true);
                        popup.show(e.getComponent(), e.getX(), e.getY());
                    }
                } else {
                    if (e.getClickCount() == 2) {
                        int index = faceB.locationToIndex(e.getPoint());
                        if (index <= faceB.getModel().getSize()) {
                            final Titre t = (Titre) faceB.getModel().getElementAt(index);
                            if (t != null && t.getLinkedFilePath() != null) {
                                try {
                                    Tools.openFile(t.getLinkedFilePath());
                                } catch (VinylManagerException ex) {
                                    VinylManagerLogger.log(ex);
                                    new ErrorWindow(MainWindow.this, ex.getMessage(), ex);
                                }
                            }
                        }
                    }
                }

            }
        });
        faceA.setListData(new Titre[0]);
        faceB.setListData(new Titre[0]);

        c.add(couleurL);
        couleur.setEditable(false);
        c.add(couleur);

        MouseAdapter ml = new MouseAdapter() {
            private boolean demi = false;

            @Override
            public void mouseClicked(MouseEvent e) {
                if (enabled) {

                    if (e.getSource() == coteL) {
                        demi = false;
                        controller.setCote(albumsList.getCurrentAlbum(), 0, demi);
                    } else {
                        for (int i = 0; i < cote.length; i++) {
                            if (e.getSource() == cote[i]) {
                                if (demi) {
                                    controller.setCote(albumsList.getCurrentAlbum(), i, demi);
                                } else {
                                    controller.setCote(albumsList.getCurrentAlbum(), i + 1, demi);
                                }

                                break;
                            }
                        }
                    }
                }
            }

            @Override
            public void mouseMoved(MouseEvent e) {
                if (enabled) {
                    demi = e.getX() < 13;
                    if (e.getSource() == coteL) {
                        setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
                    } else {
                        int selected = 0;
                        for (int i = 0; i < cote.length; i++) {
                            if (e.getSource() == cote[i]) {
                                selected = i;
                                break;
                            }
                        }

                        if (selected == 0) {
                            if (demi) {
                                cote[selected].setToolTipText("0.5 " + Language.getInstance().get("name.etoile"));
                            } else {
                                cote[selected].setToolTipText("1 " + Language.getInstance().get("name.etoile"));
                            }

                        } else {
                            if (demi) {
                                cote[selected].setToolTipText(selected + ".5 " + Language.getInstance().get("name.etoiles"));
                            } else {
                                cote[selected].setToolTipText((selected + 1) + " " + Language.getInstance().get("name.etoiles"));
                            }

                        }

                        for (int i = 0; i < cote.length; i++) {
                            if (i < selected) {
                                cote[i].setIcon(Icons.getInstance().etoilePlein);
                            } else {
                                if (i == selected) {
                                    if (demi) {
                                        cote[i].setIcon(Icons.getInstance().etoileDemi);
                                    } else {
                                        cote[i].setIcon(Icons.getInstance().etoilePlein);
                                    }
                                } else {
                                    cote[i].setIcon(Icons.getInstance().etoileVide);
                                }
                            }
                        }
                    }
                }
            }

            @Override
            public void mouseExited(MouseEvent e) {
                if (enabled) {
                    if (e.getSource() == coteL) {
                        setCursor(Cursor.getDefaultCursor());
                    } else {
                        if (albumsList.getCurrentAlbum() == null) {
                            displayCote(0, false);
                        } else {
                            displayCote(albumsList.getCurrentAlbum().getCote(), albumsList.getCurrentAlbum().getCoteDemi());
                        }
                    }
                    demi = false;
                }
            }
        };

        coteL.addMouseListener(ml);
        coteL.setToolTipText(Language.getInstance().get("name.etoile.reset"));
        c.add(coteL);

        for (int i = 0; i < cote.length; i++) {
            cote[i] = new JLabel();
            cote[i].setIcon(Icons.getInstance().etoileVide);
            cote[i].addMouseListener(ml);
            cote[i].addMouseMotionListener(ml);
            c.add(cote[i]);
        }

        AbstractAction actOriSize = new AbstractAction() {
            /**
             * uid
             */
            private static final long serialVersionUID = 123l;

            @Override
            public void actionPerformed(ActionEvent e) {
                setSize(910, 768);
            }
        };

        AbstractAction actMemInfos = new AbstractAction() {
            /**
             * uid
             */
            private static final long serialVersionUID = 2286364636L;

            @Override
            public void actionPerformed(ActionEvent e) {
                new SystemInfoWindow();
            }
        };

        sortArtistAscButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Preferences.getInstance().set(Preferences.SORT_ARTIST_DESC, "N");
                refresh();
            }
        });
        c.add(sortArtistAscButton);
        sortArtistDescButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Preferences.getInstance().set(Preferences.SORT_ARTIST_DESC, "Y");
                refresh();
            }
        });
        c.add(sortArtistDescButton);


        InputMap im = getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
        getRootPane().getActionMap().put("originalSize", actOriSize);
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_T, ActionEvent.ALT_MASK | ActionEvent.SHIFT_MASK), "originalSize");
        getRootPane().getActionMap().put("actMemInfos", actMemInfos);
        im.put(KeyStroke.getKeyStroke(KeyEvent.VK_M, ActionEvent.ALT_MASK | ActionEvent.SHIFT_MASK), "actMemInfos");
        
        setLabelText();

    }

    /**
     * Crée une nouvelle collection
     */
    private void nouveau() {
        controller.nouveau();
    }

    /**
     * Remise à 0 des champs
     */
    private void resetFields() {
        artiste.setText("");
        titre.setText("");
        compositeur.setText("");
        editeur.setText("");
        genre.setText("");
        annee.setText("");
        anneeParution.setText("");
        reference.setText("");
        chef.setText("");
        orchestre.setText("");
        support.setText("");
        valeur.setText("");
        commentaireArea.setText("");
        etat.setText("");
        etatDisque.setText("");
        vitesse.setText("");
        taille.setText("");
        canaux.setText("");
        parolier.setText("");
        location.setText("");
        couleur.setText("");
        musiciensArea.setText("");
        pays.setText("");
        dateAchat.setDate(null);

        displayCote(0, false);

        image.setIcon(null);

        disques.removeAllItems();
        disquesLabel.setText(Language.getInstance().get("name.disque") + " (0)");

        faceA.setListData(new Titre[0]);
        faceB.setListData(new Titre[0]);
    }

    /**
     * Sauver la collection
     */
    private void sauverWithWaitPanel() {
        if (!controller.isCollectionOpen()) {
            sauverSousWithWaitPanel();
        } else {
            final WaitThread waitThread = new WaitThread();
            waitThread.addWaitListener(new WaitListener() {
                @Override
                public void onCancel() {
                    waitThread.arrete();
                }
            });
            waitThread.start();
            new Thread() {
                @Override
                public void run() {
                    try {
                        controller.sauver();
                        setFrameTitle();
                    } catch (Exception ex) {
                        VinylManagerLogger.log(ex);
                        openWindow = new ErrorWindow(MainWindow.this, ex.getMessage(), ex);
                    } finally {
                        waitThread.arrete();
                    }
                }
            }.start();

        }
    }

    private void sauver() {
        if (!controller.isCollectionOpen()) {
            sauverSous();
        } else {
            try {
                controller.sauver();
                setFrameTitle();
            } catch (VinylManagerException ex) {
                VinylManagerLogger.log(ex);
                openWindow = new ErrorWindow(this, ex.getMessage(), ex);
            }
        }
    }

    private void sauverSous() {
        try {
            setEnabled(false);
            JFileChooser fc = new JFileChooser(Preferences.getInstance().get(Preferences.PATH_SAVE, System.getProperty("user.home")));
            fc.setDialogTitle(Language.getInstance().get("export.dialog.title"));
            fc.setMultiSelectionEnabled(false);
            fc.setAcceptAllFileFilterUsed(false);
            fc.setFileFilter(new FileFilterVM());
            int res = fc.showSaveDialog(this);
            setEnabled(true);

            if (res == JFileChooser.APPROVE_OPTION) {
                File f = fc.getSelectedFile();
                Preferences.getInstance().set(Preferences.PATH_SAVE, f.getParentFile().getAbsolutePath());
                if (!f.getAbsolutePath().toLowerCase().endsWith(".vm")) {
                    f = new File(f.getAbsolutePath() + ".vm");
                }

                if (f.exists()) {
                    int result = JOptionPane.showConfirmDialog(this, Language.getInstance().get("save.overwrite.dialog").replace("%1", f.getName()), Language.getInstance().get("save.overwrite.title"), JOptionPane.YES_NO_OPTION);
                    switch (result) {
                        case JOptionPane.YES_OPTION:
                            controller.sauver(f);
                            setFrameTitle();
                            break;
                        case JOptionPane.NO_OPTION:
                            break;
                    }
                } else {
                    controller.sauver(f);
                    setFrameTitle();
                }
            }

            toFront();
        } catch (Exception e) {
            VinylManagerLogger.log(e);
            openWindow = new ErrorWindow(this, Language.getInstance().get("error.save.message"), e);
        }
    }

    /**
     * Enregistrer sous...
     */
    private void sauverSousWithWaitPanel() {
        setEnabled(false);
        JFileChooser fc = new JFileChooser(Preferences.getInstance().get(Preferences.PATH_SAVE, System.getProperty("user.home")));
        fc.setDialogTitle(Language.getInstance().get("export.dialog.title"));
        fc.setMultiSelectionEnabled(false);
        fc.setAcceptAllFileFilterUsed(false);
        fc.setFileFilter(new FileFilterVM());
        int res = fc.showSaveDialog(this);
        setEnabled(true);

        if (res == JFileChooser.APPROVE_OPTION) {
            File fts = fc.getSelectedFile();
            Preferences.getInstance().set(Preferences.PATH_SAVE, fts.getParentFile().getAbsolutePath());
            if (!fts.getAbsolutePath().toLowerCase().endsWith(".vm")) {
                fts = new File(fts.getAbsolutePath() + ".vm");
            }

            final File f = fts;
            final WaitThread waitThread = new WaitThread();
            waitThread.addWaitListener(new WaitListener() {
                @Override
                public void onCancel() {
                    waitThread.arrete();
                }
            });
            waitThread.start();
            new Thread() {
                @Override
                public void run() {
                    try {
                        if (f.exists()) {
                            int result = JOptionPane.showConfirmDialog(MainWindow.this, Language.getInstance().get("save.overwrite.dialog").replace("%1", f.getName()), Language.getInstance().get("save.overwrite.title"), JOptionPane.YES_NO_OPTION);
                            switch (result) {
                                case JOptionPane.YES_OPTION:
                                    controller.sauver(f);
                                    setFrameTitle();
                                    break;
                                case JOptionPane.NO_OPTION:
                                    break;
                            }
                        } else {
                            controller.sauver(f);
                            setFrameTitle();
                        }
                    } catch (Exception e) {
                        VinylManagerLogger.log(e);
                        openWindow = new ErrorWindow(MainWindow.this, Language.getInstance().get("error.save.message"), e);
                    } finally {
                        waitThread.arrete();
                    }
                }
            }.start();
        }

        toFront();

    }

    /**
     * Fusion d'une collection.
     */
    private void append() {
        try {
            setEnabled(false);
            JFileChooser fc = new JFileChooser(Preferences.getInstance().get(Preferences.PATH_LOAD, System.getProperty("user.home")));
            fc.setDialogTitle(Language.getInstance().get("open.dialog.title"));
            fc.setMultiSelectionEnabled(false);
            fc.setAcceptAllFileFilterUsed(false);
            fc.setFileFilter(new FileFilterVM());
            int res = fc.showOpenDialog(this);
            setEnabled(true);
            if (res == JFileChooser.APPROVE_OPTION) {
                File f = fc.getSelectedFile();
                Preferences.getInstance().set(Preferences.PATH_LOAD, f.getParentFile().getAbsolutePath());
                if (f.exists()) {
                    controller.fusion(f);
                } else {
                    new ErrorWindow(this, Language.getInstance().get("error.file.not.exists").replace("%1", f.getAbsolutePath()));
                }
            }
            toFront();

        } catch (VinylManagerException e) {
            VinylManagerLogger.log(e);
            openWindow = new ErrorWindow(this, Language.getInstance().get("error.open.message"), e);
        }
    }

    /**
     * ouvrir un fichier
     */
    private void open() {
        setEnabled(false);
        JFileChooser fc = new JFileChooser(Preferences.getInstance().get(Preferences.PATH_LOAD, System.getProperty("user.home")));
        fc.setDialogTitle(Language.getInstance().get("open.dialog.title"));
        fc.setMultiSelectionEnabled(false);
        fc.setAcceptAllFileFilterUsed(false);
        fc.setFileFilter(new FileFilterVM());
        int res = fc.showOpenDialog(this);
        setEnabled(true);
        if (res == JFileChooser.APPROVE_OPTION) {
            File f = fc.getSelectedFile();
            Preferences.getInstance().set(Preferences.PATH_LOAD, f.getParentFile().getAbsolutePath());
            if (f.exists()) {
                openFile(f.getAbsolutePath());
            } else {
                new ErrorWindow(this, Language.getInstance().get("error.file.not.exists").replace("%1", f.getAbsolutePath()));
            }
        }
        toFront();
    }

    private void openFile(final String fileName) {
        final WaitThread waitThread = new WaitThread();
        waitThread.addWaitListener(new WaitListener() {
            @Override
            public void onCancel() {
                waitThread.arrete();
            }
        });
        waitThread.start();
        new Thread() {
            @Override
            public void run() {
                try {
                    controller.open(fileName);
                } catch (VinylManagerException ex) {
                    VinylManagerLogger.log(ex);
                    openWindow = new ErrorWindow(MainWindow.this, Language.getInstance().get("error.open.message"), ex);
                } finally {
                    waitThread.arrete();
                }
            }
        }.start();
    }

    private void addFileToTitre(Titre t) {

        setEnabled(false);
        JFileChooser fc = new JFileChooser(Preferences.getInstance().get(Preferences.PATH_TRACKFILE, System.getProperty("user.home")));
        fc.setDialogTitle(Language.getInstance().get("open.dialog.title"));
        fc.setMultiSelectionEnabled(false);
        fc.setAcceptAllFileFilterUsed(false);
        int res = fc.showOpenDialog(this);
        setEnabled(true);
        if (res == JFileChooser.APPROVE_OPTION) {
            File f = fc.getSelectedFile();
            if (f.exists()) {
                t.setLinkedFilePath(f.getAbsolutePath());
                Preferences.getInstance().set(Preferences.PATH_TRACKFILE, f.getParentFile().getAbsolutePath());
            } else {
                new ErrorWindow(this, Language.getInstance().get("error.file.not.exists").replace("%1", f.getAbsolutePath()));
            }
        }
        toFront();

    }

    /**
     * importe une collection
     */
    private void importCollection() {

        setEnabled(false);
        JFileChooser fc = new JFileChooser(Preferences.getInstance().get(Preferences.PATH_IMPORT, System.getProperty("user.home")));
        fc.setDialogTitle(Language.getInstance().get("open.dialog.title"));
        fc.setMultiSelectionEnabled(false);
        fc.setAcceptAllFileFilterUsed(false);
        fc.setFileFilter(new FileFilterImport());
        int res = fc.showOpenDialog(MainWindow.this);
        setEnabled(true);
        if (res == JFileChooser.APPROVE_OPTION) {
            final File f = fc.getSelectedFile();
            if (f.exists() && f.isFile()) {
                Preferences.getInstance().set(Preferences.PATH_IMPORT, f.getParentFile().getAbsolutePath());
                final WaitThread waitThread = new WaitThread();
                waitThread.addWaitListener(new WaitListener() {
                    @Override
                    public void onCancel() {
                        waitThread.arrete();
                    }
                });
                waitThread.start();
                new Thread() {
                    @Override
                    public void run() {
                        try {
                            if (f.getName().toLowerCase().endsWith("csv")) {
                                controller.importCollectionCsv(f);
                            } else {
                                controller.importCollectionXml(f);
                            }
                        } catch (VinylManagerException ex) {
                            VinylManagerLogger.log(ex);
                            new ErrorWindow(MainWindow.this, Language.getInstance().get("error.open.message"), ex);
                        } finally {
                            waitThread.arrete();
                        }
                    }
                }.start();

            } else {
                new ErrorWindow(this, Language.getInstance().get("error.file.not.exists").replace("%1", f.getAbsolutePath()));
            }
        }
        toFront();

    }

    /**
     * quitter l'application
     */
    private void quitter() {
        if (controller.isModified()) {
            int result = JOptionPane.showConfirmDialog(this, Language.getInstance().get("confirm.save.dialog"), Language.getInstance().get("confirm.save.title"), JOptionPane.YES_NO_CANCEL_OPTION);
            switch (result) {
                case JOptionPane.YES_OPTION:
                    Preferences.getInstance().save();
                    sauver();
                    memory.stop();
                    VinylManagerLogger.exit();
                    System.exit(0);
                    break;
                case JOptionPane.NO_OPTION:
                    Preferences.getInstance().save();
                    memory.stop();
                    VinylManagerLogger.exit();
                    System.exit(0);
                    break;
                case JOptionPane.CANCEL_OPTION:
                    break;
            }
        } else {
            Preferences.getInstance().save();
            memory.stop();
            VinylManagerLogger.exit();
            System.exit(0);
        }

    }

    /**
     * Sélection d'un album et d'un disque.
     *
     * @param album
     * @param disqueIdx
     */
    public void select(Album album, int disqueIdx) {
        resetFields();
        select(album);
        if (disqueIdx > 0) {
            disques.setSelectedIndex(disqueIdx);
        }
    }

    /**
     * Affiche l'album sélectionné.
     */
    private void showAlbum() {
        Album al = albumsList.getCurrentAlbum();
        if (al == null) {
            resetFields();
            return;
        }

        disques.removeAllItems();
        faceA.setListData(new Titre[0]);
        faceB.setListData(new Titre[0]);
        int nbrDisques = 0;
        for (Disque d : al.getDisques()) {
            disques.addItem(d);
            nbrDisques++;
        }
        disquesLabel.setText(Language.getInstance().get("name.disque") + " (" + nbrDisques + ")");

        titre.setText(al.getTitre());
        annee.setText(al.getAnnee());
        anneeParution.setText(al.getAnneeParution());
        artiste.setText(al.getArtiste());
        commentaireArea.setText(al.getCommentaire());
        genre.setText(al.getGenre());
        editeur.setText(al.getEditeur());
        etat.setText(Cotation.getCotation(al.getEtat()));
        musiciensArea.setText(al.getMusiciens());
        reference.setText(al.getReference());
        valeur.setText(al.getValeur());
        chef.setText(al.getChef());
        orchestre.setText(al.getOrchestre());
        dateAchat.setDate(al.getDateAchat());
        compositeur.setText(al.getCompositeur());
        support.setText(Support.getSupport(al.getSupport()).getName());
        parolier.setText(al.getParolier());
        location.setText(al.getLocation());
        pays.setText(al.getPays());

        selectedImage = null;

        currentImg = -1;
        try {
            displayImage();
        } catch (VinylManagerException ex) {
            VinylManagerLogger.log(ex);
            openWindow = new ErrorWindow(this, Language.getInstance().get("error.image.message"), ex);
        }

        displayCote(al.getCote(), al.getCoteDemi());
    }

    private void displayImage() throws VinylManagerException {
        if (albumsList.getCurrentAlbum() != null) {
            Album al = albumsList.getCurrentAlbum();
            if (al.getImage() == null) {
                image.setIcon(null);
                imgPrev.setVisible(false);
                imgNext.setVisible(false);
                currentImg = -1;
            } else {
                if (currentImg == -1) {
                    selectedImage = al.getImage().getContenu();
                    if (selectedImage != null)  {
                        image.setIcon(new ImageIcon(Tools.getReducedImage(selectedImage)));                        
                    } else {
                        image.setIcon(null);
                    }
                    imgPrev.setVisible(false);
                    if (al.getOtherImages() == null || al.getOtherImages().isEmpty()) {
                        imgNext.setVisible(false);
                    } else {
                        imgNext.setVisible(true);
                    }
                } else {
                    be.msyben.vinylManager.entities.Image i = al.getOtherImages().get(currentImg);
                    if (i != null && i.getContenu() != null) {
                        selectedImage = i.getContenu();
                        image.setIcon(new ImageIcon(Tools.getReducedImage(selectedImage)));                        
                    } else {
                        selectedImage = null;
                        image.setIcon(null);
                    }
                    imgPrev.setVisible(true);
                    if (currentImg == al.getOtherImages().size() - 1) {
                        imgNext.setVisible(false);
                    } else {
                        imgNext.setVisible(true);
                    }
                }
            }
        } else {
            image.setIcon(null);
            imgPrev.setVisible(false);
            imgNext.setVisible(false);
            currentImg = -1;
        }
    }

    /**
     * Affichage du disque sélectionné disque.
     */
    private void showDisque() {
        Disque disque = (Disque) disques.getSelectedItem();
        if (disque == null) {
            vitesse.setText("");
            taille.setText("");
            couleur.setText("");
            canaux.setText("");
            return;
        }

        etatDisque.setText(Cotation.getCotation(disque.getEtat()));

        String dureeA = disque.getDureeTotaleFace(true);
        String dureeB = disque.getDureeTotaleFace(false);
        boolean showDuration = Preferences.getInstance().get(Preferences.DISPLAY_DURATION_SIDE, "Y").equalsIgnoreCase("Y");
        
        
        if (showDuration && dureeA != null) {
            faceALabel.setText(Language.getInstance().get("name.faceA") + " (" + dureeA + ")");
        } else  {
            faceALabel.setText(Language.getInstance().get("name.faceA"));
        }
        if (showDuration && dureeB != null) {   
            faceBLabel.setText(Language.getInstance().get("name.faceB") + " (" + dureeB + ")");
        } else {
            faceBLabel.setText(Language.getInstance().get("name.faceB"));
        }
        
        faceA.setListData(new Titre[0]);
        faceB.setListData(new Titre[0]);

        faceA.setListData(disque.getFaceA().toArray(new Titre[0]));
        faceB.setListData(disque.getFaceB().toArray(new Titre[0]));

        Album al = albumsList.getCurrentAlbum();
        if (al != null) {
            Support sup = Support.getSupport(al.getSupport());
            if (sup == Support.vinyl) {
                vitesse.setText(Vitesse.getVitesse(disque.getVitesse()).getName());
                taille.setText(Taille.getTaille(disque.getTaille()).getName());
            } else if(sup == Support.schellack) {
                if (disque.getVitesse() == null) {
                    disque.setVitesse(Vitesse.vitesse78.getId());
                }
                vitesse.setText(Vitesse.getVitesse(disque.getVitesse()).getName());
                taille.setText(sup.getName());
            } else {
                vitesse.setText(sup.getName());
                taille.setText(sup.getName());
            }
        } else {
            vitesse.setText("");
            taille.setText("");
        }
        couleur.setText(disque.getCouleur());
        if (disque.getCanaux() != null) {
            canaux.setText(Canaux.getCanaux(disque.getCanaux()).getName());
        }
    }
    
    /**
     * Importe une collection depuis Discogs.
     */
    private void importDiscogs() {
        final String username = JOptionPane.showInputDialog(MainWindow.this, Language.getInstance().get("discogs.import.collection.message"), Language.getInstance().get("discogs.import.collection.title"), JOptionPane.QUESTION_MESSAGE);
        boolean ignoreDuplicates = true;
        final WaitThread wt = new WaitThread(true);
        wt.addWaitListener(new WaitListener() {
            @Override
            public void onCancel() {
                wt.arrete();
            }
        });
        wt.start();
        new Thread() {
            @Override
            public void run() {
                try {
                    Set<String> dicosgsIds = controller.getDiscogsIds();
                    List<Album> albums = DiscogsSearch.getDiscogsUserReleases(username, wt);
                    if (wt.isRunning()) {
                        for (Album a : albums) {
                            boolean add = true;
                            if (ignoreDuplicates) {
                                String currentId = a.getDiscogsId();
                                if (currentId != null && !currentId.isEmpty() && dicosgsIds.contains(currentId)) {
                                    add = false;
                                }
                            }
                            if (add) {
                                controller.addAlbum(a);
                            }
                        }
                    }
                } catch (VinylManagerException ex) {
                    ex.printStackTrace(); 
                } finally {
                    wt.arrete();
                }
            }
        }.start();
    }

    /**
     * Met à jour la cote de l'album
     */
    private void displayCote(int currentCote, boolean demi) {
        for (int i = 0; i < cote.length; i++) {
            if (i < currentCote) {
                cote[i].setIcon(Icons.getInstance().etoilePlein);
            } else {
                if (i == currentCote && demi) {
                    cote[i].setIcon(Icons.getInstance().etoileDemi);
                } else {
                    cote[i].setIcon(Icons.getInstance().etoileVide);
                }
            }
        }
    }
    private boolean enabled = true;

    /**
     * Désactive les éléments de la fenêtre.
     *
     * @param enabled activé ou pas
     */
    @Override
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
        super.setEnabled(enabled);
        menuBar.setEnabled(enabled);
        fichier.setEnabled(enabled);
        action.setEnabled(enabled);
        aide.setEnabled(enabled);
        leftList.setEnabled(enabled);
        albumsList.setEnabled(enabled);
        disques.setEnabled(enabled);
        image.setEnabled(enabled);
        for (JLabel cote1 : cote) {
            cote1.setEnabled(enabled);
        }
        if (enabled) {
            openWindow = null;
            toFront();
        }
    }

    /**
     * Crée la liste de gauche en fonction des préférences.
     */
    private void makeLeftList() {
        int affichageChoisi = Integer.parseInt(Preferences.getInstance().get(Preferences.AFFICHAGE, "1"));
        switch (affichageChoisi) {
            case 1:
                leftList = new SelectionnableFieldList();
                break;
            case 2:
                leftList = new VinylManagerTree();
                break;
            default:
                leftList = new ArtistList();
                break;
        }
        leftList.addListListener(new LeftListListener() {
            @Override
            public void selection(List<Album> albums) {
                Sort.sort(albums, "annee", "titre");
                albumsList.updateList(albums);
            }
        });

    }

    /**
     * Rafraichi suite à une modification des préférences.
     */
    public void refreshFromPreferences() {
        Language.getInstance().reload();
        ProxySettings.setProxy();

        FontTool.refreshFont(this);

        setFrameTitle();
        Rectangle bounds = leftList.getComponent().getBounds();
        Dimension size = leftList.getComponent().getSize();
        this.getContentPane().remove(leftList.getComponent());
        makeLeftList();
        setLabelText();
        leftList.getComponent().setBounds(bounds.x, bounds.y, size.width, size.height);
        this.getContentPane().add(leftList.getComponent());
        this.getContentPane().repaint();
        dateAchat.setDateFormatString(Preferences.getInstance().get(Preferences.DATE_FORMAT, "dd/MM/yyyy"));
        refresh();
    }
    
    /**
     * Permet de définit la fenêtre ouverte courante si il y a un changement depuis une fenêtre secondaire.
     * @param openWindow la fenêtre
     */
    public void setOpenWindow(JFrame openWindow) {
        this.openWindow = openWindow;
    }
}
