package be.msyben.vinylManager.tools.importexport;

import be.msyben.vinylManager.entities.Album;
import be.msyben.vinylManager.entities.Collection;
import be.msyben.vinylManager.entities.Disque;
import be.msyben.vinylManager.entities.Image;
import be.msyben.vinylManager.entities.Titre;
import be.msyben.vinylManager.exceptions.VinylManagerException;
import be.msyben.vinylManager.properties.*;
import be.msyben.vinylManager.tools.Sort;
import be.msyben.vinylManager.tools.Tools;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;

/**
 * Exporte la collection en HTML dans le répertoire défini.
 * @author Mathieu Syben
 */
public final class HtmlExport {

    private static final int BUFFER = 2048;
    private static final DateFormat df = new SimpleDateFormat("dd/MM/yyyy");

    /**
     * Constructeur privé.
     */
    private HtmlExport() {
    }

    /**
     * Exporte en html
     * @param f le répertoire de destination
     * @param collection la collection à exporter
     * @throws VinylManagerException en cas d'erreur
     */
    public static void htmlExport(File f, Collection collection) throws VinylManagerException {

        String modeleName = Preferences.getInstance().get(Preferences.EXPORT_HTML_FILE);
        InputStream modele = null;
        if (modeleName == null || modeleName.equals("")) {
            modele = HtmlExport.class.getResourceAsStream("/be/msyben/vinylManager/tools/importexport/export.zip");
        } else {
            File zipFile = new File("export_html" + System.getProperty("file.separator") + modeleName + ".zip");
            try {
                modele = new FileInputStream(zipFile);
            } catch (FileNotFoundException ex) {
                throw new VinylManagerException(ex);
            }
        }

        // dézippage
        Map<String, byte[]> files = new HashMap<String, byte[]>();
        ZipInputStream zis = null;
        try {
            zis = new ZipInputStream(modele);

            ZipEntry entry;
            byte data[] = new byte[BUFFER];

            while ((entry = zis.getNextEntry()) != null) {
                String name = entry.getName();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                int count;
                while ((count = zis.read(data, 0, BUFFER)) != -1) {
                    baos.write(data, 0, count);
                }

                byte[] content = baos.toByteArray();

                if (name.toLowerCase().endsWith(".html")) {
                    files.put(name, content);
                } else {
                    if (!entry.isDirectory()) {
                        writeFile(content, new File(f.getAbsolutePath() + System.getProperty("file.separator") + name));
                    } else {
                        File fd = new File(f.getAbsolutePath() + System.getProperty("file.separator") + name);
                        if (fd.exists() && !fd.isDirectory()) {
                            throw new VinylManagerException(Language.getInstance().get("error.export.html.file.exists.directory").replace("%1", name));
                        }
                        fd.mkdir();
                    }
                }
            }
        } catch (IOException ex) {
            throw new VinylManagerException(ex);
        } finally {
            Tools.closeQuietly(modele);
            Tools.closeQuietly(zis);
        }

        if (!files.containsKey("index.html")) {
            throw new VinylManagerException(Language.getInstance().get("error.export.html.file.not.exist").replace("%1", "index.html"));
        }

        Artiste.reset();

        // Création du répertoires images.
        String imagesRepName = f.getAbsolutePath() + System.getProperty("file.separator") + "images";
        File imagesRep = new File(imagesRepName);
        if (imagesRep.exists() && !imagesRep.isDirectory()) {
            throw new VinylManagerException(Language.getInstance().get("error.export.html.images.invalid"));
        }
        if (!imagesRep.exists()) {
            imagesRep.mkdir();
        }

        // Création de la collection des artistes (séparation par artiste des albums)
        Map<String, Artiste> allArtistes = new HashMap<String, Artiste>();
        for (Album a : collection.getAlbums()) {
            Artiste art = allArtistes.get(a.getArtisteForSorting());
            if (art == null) {
                art = new Artiste();
                art.setNom(a.getArtisteForList());
                art.setNomTri(a.getArtisteForSorting());
                allArtistes.put(a.getArtisteForSorting(), art);
            }
            art.addAlbum(a);
        }

        //Ecriture du fichier index.html
        writeFile(processContenuMain(files.get("index.html"), allArtistes, f.getAbsolutePath(), files), new File(f.getAbsolutePath() + System.getProperty("file.separator") + "index.html"));
    }

    /**
     * Ecrit le contenu du fichier à la recherche des 'loopArtiste'.
     * @param contenuArray le contenu
     * @param allArtistes la map contenant tous les artistes
     * @param filePath le path du répertoire où écrire les fichiers
     * @param files les fichiers du zip
     * @return le contenu modifié
     * @throws VinylManagerException en cas d'erreur
     */
    private static byte[] processContenuMain(byte[] contenuArray, Map<String, Artiste> allArtistes, String filePath, Map<String, byte[]> files) throws VinylManagerException {
        String contenu = new String(contenuArray, Tools.defaultCharset);
        while (contenu.contains("<loopArtiste>")) {
            int indexDeb = contenu.indexOf("<loopArtiste>");
            int indexFin = contenu.indexOf("</loopArtiste>");
            if (indexFin < indexDeb) {
                throw new VinylManagerException(Language.getInstance().get("error.export.html.loop.artiste.invalid"));
            }
            String debut = contenu.substring(0, indexDeb);
            String toMod = contenu.substring(indexDeb + 13, indexFin);
            StringBuilder mid = new StringBuilder("");
            String fin = contenu.substring(indexFin + 14);

            Set<String> artistesSet = allArtistes.keySet();
            List<String> artistes = new ArrayList<String>(artistesSet);
            Sort.sort(artistes);
            for (String artiste : artistes) {
                Artiste art = allArtistes.get(artiste);
                String temp = toMod.replace("%artiste%", Tools.formatHtml(art.getNom()));
                temp = new String(processContenuAlbums(temp.getBytes(Tools.defaultCharset), allArtistes.get(artiste).getAlbums(), filePath, files), Tools.defaultCharset);

                // liens vers l'artiste
                while (temp.contains("<link page=\"")) {
                    int indexLinkDeb = temp.indexOf("<link page=\"");
                    int indexLinkFin = temp.indexOf("</link>");
                    if (indexLinkFin < indexLinkDeb) {
                        throw new VinylManagerException(Language.getInstance().get("error.export.html.link.invalid"));
                    }
                    String ttt = temp.substring(indexLinkDeb + 5, indexLinkFin);
                    ttt = ttt.substring(ttt.indexOf("\"") + 1);
                    String lien = ttt.substring(0, ttt.indexOf("\""));
                    String contenuLien = ttt.substring(ttt.indexOf(">") + 1);

                    lien = createLienArtiste(filePath, lien, contenuLien, files, allArtistes.get(artiste));
                    temp = temp.substring(0, indexLinkDeb) + lien + temp.substring(indexLinkFin + 7);
                }

                mid.append(temp);
            }

            contenu = debut + mid.toString() + fin;
        }


        return contenu.getBytes(Tools.defaultCharset);
    }

    /**
     * Crée un lien pour un artiste (lien dans la boucle 'loopArtiste')
     * @param filePath le path du répertoire où écrire les fichiers
     * @param fileName Le nom du fichier pour le lien
     * @param contenu Le contenu du lien (qui sera dans <a>xxx</a>
     * @param files les fichiers du zip
     * @param artiste L'artiste pour lequel le lien est crée
     * @return le lien à introduire dans le fichier html
     * @throws VinylManagerException en cas d'erreur
     */
    private static String createLienArtiste(String filePath, String fileName, String contenu, Map<String, byte[]> files, Artiste artiste) throws VinylManagerException {
        byte[] lienFile = files.get(fileName);
        if (lienFile == null) {
            throw new VinylManagerException(Language.getInstance().get("error.export.html.file.not.exist").replace("%1", fileName));
        }

        byte[] temp = processContenuAlbums(lienFile, artiste.getAlbums(), filePath, files);

        writeFile(temp, new File(filePath + System.getProperty("file.separator") + artiste.getNbrArtiste() + fileName));

        return "<a href=\"" + artiste.getNbrArtiste() + fileName + "\">" + contenu + "</a>";

    }

    /**
     * Modifie le contenu pour y introduire les informations des albums d'un artiste dans une boucle 'loopAlbum'
     * @param contenuArray le contenu
     * @param albums La liste des albums de l'artiste
     * @param filePath le path du répertoire où écrire les fichiers
     * @param files les fichiers du zip
     * @return le contenu modifié
     * @throws VinylManagerException en cas d'erreur
     */
    private static byte[] processContenuAlbums(byte[] contenuArray, List<AlbumExt> albums, String filePath, Map<String, byte[]> files) throws VinylManagerException {
        String contenu = new String(contenuArray, Tools.defaultCharset);
        while (contenu.contains("<loopAlbum>")) {
            int indexDeb = contenu.indexOf("<loopAlbum>");
            int indexFin = contenu.indexOf("</loopAlbum>");
            if (indexFin < indexDeb) {
                throw new VinylManagerException(Language.getInstance().get("error.export.html.loop.album.invalid"));
            }
            String debut = contenu.substring(0, indexDeb);
            String toMod = contenu.substring(indexDeb + 11, indexFin);
            StringBuilder mid = new StringBuilder("");
            String fin = contenu.substring(indexFin + 12);

            Sort.sort(albums);
            for (AlbumExt album : albums) {
                String temp = modForAlbum(toMod, album, filePath, files);
                mid.append(temp);
            }

            String artiste = "";
            if (albums.size() > 0) {
                artiste = Tools.formatHtml(albums.get(0).getAlbum().getArtisteForList());
            }
            
            debut = debut.replace("%artiste%", artiste);
            fin = fin.replace("%artiste%", artiste);
            
            contenu = debut + mid.toString() + fin;
        }

        return contenu.getBytes(Tools.defaultCharset);
    }

    /**
     * Modifie la string pour y introduire les infos pour l'album
     * @param toMod la string à modifier
     * @param album l'album dont les données devront être introduites
     * @param filePath le path du répertoire où écrire les fichiers
     * @param files les fichiers du zip
     * @return la string modifiée
     * @throws VinylManagerException en cas d'erreur
     */
    private static String modForAlbum(String toMod, AlbumExt album, String filePath, Map<String, byte[]> files) throws VinylManagerException {
        String temp = toMod.replace("%annee%", Tools.formatHtml(album.getAlbum().getAnnee()));
        temp = temp.replace("%anneeParution%", Tools.formatHtml(album.getAlbum().getAnneeParution()));
        temp = temp.replace("%artiste%", Tools.formatHtml(album.getAlbum().getArtisteForList()));
        temp = temp.replace("%commentaire%", Tools.formatHtml(album.getAlbum().getCommentaire()));
        temp = temp.replace("%pays%", Tools.formatHtml(album.getAlbum().getPays()));
        temp = temp.replace("%editeur%", Tools.formatHtml(album.getAlbum().getEditeur()));
        temp = temp.replace("%etat%", Tools.formatHtml(album.getAlbum().getEtat()));
        temp = temp.replace("%genre%", Tools.formatHtml(album.getAlbum().getGenre()));
        temp = temp.replace("%musiciens%", Tools.formatHtml(album.getAlbum().getMusiciens()));
        temp = temp.replace("%reference%", Tools.formatHtml(album.getAlbum().getReference()));
        temp = temp.replace("%titre%", Tools.formatHtml(album.getAlbum().getTitre()));
        temp = temp.replace("%valeur%", Tools.formatHtml(album.getAlbum().getValeur()));
        temp = temp.replace("%chef%", Tools.formatHtml(album.getAlbum().getChef()));
        temp = temp.replace("%orchestre%", Tools.formatHtml(album.getAlbum().getOrchestre()));
        temp = temp.replace("%compositeur%", Tools.formatHtml(album.getAlbum().getCompositeur()));
        temp = temp.replace("%possede%", album.getAlbum().getPossede()?"true":"false");
        
        temp = temp.replace("%parolier%", Tools.formatHtml(album.getAlbum().getParolier()));
        temp = temp.replace("%location%", Tools.formatHtml(album.getAlbum().getLocation()));
        temp = temp.replace("%dateAchat%", album.getAlbum().getDateAchat()==null?"":df.format(album.getAlbum().getDateAchat()));
        
        
        Support support = Support.getSupport(album.getAlbum().getSupport());
        temp = temp.replace("%support%", Tools.formatHtml(support.getName()));
        String cote = "";
        if (album.getAlbum().getCote() > 0) {
            cote += album.getAlbum().getCote();
            if (album.getAlbum().getCoteDemi()) {
                cote += ".5";
            }
            cote += "/5";
        }
        temp = temp.replace("%cote%", cote);
        
        String imageS = "";
        Image image = album.getAlbum().getImage();
        if (image != null && image.getContenu().length > 0) {
            writeFile(image.getContenu(), new File(filePath + System.getProperty("file.separator") + "images" + System.getProperty("file.separator") + "img" + album.getNbr() + ".jpg"));
            imageS = "<img src=\"images/img" + album.getNbr() + ".jpg\" alt=\"Image\">\r\n";
        }
        temp = temp.replace("%image%", imageS);

        while (temp.contains("<loopOtherImages>")) {
            int indexDeb = temp.indexOf("<loopOtherImages>");
            int indexFin = temp.indexOf("</loopOtherImages>");
            if (indexFin < indexDeb) {
                throw new VinylManagerException(Language.getInstance().get("error.export.html.loop.image.invalid"));
            }
            String debut = temp.substring(0, indexDeb);
            String toModImage = temp.substring(indexDeb + 17, indexFin);
            StringBuilder mid = new StringBuilder("");
            String fin = temp.substring(indexFin + 18);

            if (album.getAlbum().getOtherImages() != null && !album.getAlbum().getOtherImages().isEmpty()){
                System.out.println("Loop autres images pour " + album.getAlbum().getTitre());
                int idx = 0;
                for (Image i : album.getAlbum().getOtherImages()) {
                    String tempImage = toModImage;
                    writeFile(i.getContenu(), new File(filePath + System.getProperty("file.separator") + "images" + System.getProperty("file.separator") + "img" + album.getNbr() +"-"+idx+ ".jpg"));
                    String loopImageValue = "<img src=\"images/img" + album.getNbr()+"-"+idx + ".jpg\" alt=\"Image\">\r\n";
                    tempImage = tempImage.replace("%otherImage%", loopImageValue);
                    mid.append(tempImage);
                    idx++;
                }
            }            
            temp = debut + mid.toString() + fin;
        }

        // liens vers l'album
        while (temp.contains("<link page=\"")) {
            int indexLinkDeb = temp.indexOf("<link page=\"");
            int indexLinkFin = temp.indexOf("</link>");
            if (indexLinkFin < indexLinkDeb) {
                throw new VinylManagerException(Language.getInstance().get("error.export.html.link.invalid"));
            }
            String ttt = temp.substring(indexLinkDeb + 5, indexLinkFin);
            ttt = ttt.substring(ttt.indexOf("\"") + 1);
            String lien = ttt.substring(0, ttt.indexOf("\""));
            String contenuLien = ttt.substring(ttt.indexOf(">") + 1);

            lien = createLienAlbum(filePath, lien, contenuLien, files, album);
            temp = temp.substring(0, indexLinkDeb) + lien + temp.substring(indexLinkFin + 7);
        }

        temp = new String(processContenuDisques(temp.getBytes(Tools.defaultCharset), album.getAlbum().getDisques()), Tools.defaultCharset);
        return temp;
    }

    /**
     * Crée un lien pour un album.
     * @param filePath le path du répertoire où écrire les fichiers
     * @param fileName le nom du fichier à créer
     * @param contenu Le contenu du lien (qui sera dans <a>xxx</a>
     * @param files les fichiers du zip
     * @param album l'album pour lequel le lien est fait
     * @return le lien à introduire dans le fichier html
     * @throws VinylManagerException en cas d'erreur
     */
    private static String createLienAlbum(String filePath, String fileName, String contenu, Map<String, byte[]> files, AlbumExt album) throws VinylManagerException {
        byte[] lienFile = files.get(fileName);
        if (lienFile == null) {
            throw new VinylManagerException(Language.getInstance().get("error.export.html.file.not.exist").replace("%1", fileName));
        }

        String toMod = new String(lienFile, Tools.defaultCharset);
        String temp = modForAlbum(toMod, album, filePath, files);

        writeFile(temp.getBytes(Tools.defaultCharset), new File(filePath + System.getProperty("file.separator") + album.getNbr() + fileName));

        return "<a href=\"" + album.getNbr() + fileName + "\">" + contenu + "</a>";
    }

    /**
     * Modifie le contenu pour y introduire les informations des albums d'un artiste dans une boucle 'loopDisque'
     * @param contenuArray le contenu
     * @param disques la liste des disques
     * @return le contenu modifié
     * @throws VinylManagerException en cas d'erreur
     */
    private static byte[] processContenuDisques(byte[] contenuArray, List<Disque> disques) throws VinylManagerException {
        String contenu = new String(contenuArray, Tools.defaultCharset);
        while (contenu.contains("<loopDisque>")) {
            int indexDeb = contenu.indexOf("<loopDisque>");
            int indexFin = contenu.indexOf("</loopDisque>");
            if (indexFin < indexDeb) {
                throw new VinylManagerException(Language.getInstance().get("error.export.html.loop.disque.invalid"));
            }
            String debut = contenu.substring(0, indexDeb);
            String toMod = contenu.substring(indexDeb + 12, indexFin);
            StringBuilder mid = new StringBuilder("");
            String fin = contenu.substring(indexFin + 13);
            for (Disque disque : disques) {
                String temp = toMod;
                temp = temp.replace("%disqueEtat%", Tools.formatHtml(disque.getEtat()));
                temp = temp.replace("%couleur%", Tools.formatHtml(disque.getCouleur()));
                String vitesse = "";
                if (disque.getVitesse() != null) {
                    vitesse = Vitesse.getVitesse(disque.getVitesse()).getName();
                }
                temp = temp.replace("%vitesse%", Tools.formatHtml(vitesse));
                String taille = "";
                if (disque.getTaille() != null) {
                    taille = Taille.getTaille(disque.getTaille()).getName();
                }
                temp = temp.replace("%taille%", Tools.formatHtml(taille));
                String canaux = "";
                if (disque.getCanaux() != null) {
                    canaux = Canaux.getCanaux(disque.getCanaux()).getName();
                }
                temp = temp.replace("%canaux%", Tools.formatHtml(canaux));
                temp = temp.replace("%disqueNum%", ""+disque.getNum());
                temp = new String(processContenuTitresA(temp.getBytes(Tools.defaultCharset), disque.getFaceA()), Tools.defaultCharset);
                temp = new String(processContenuTitresB(temp.getBytes(Tools.defaultCharset), disque.getFaceB()), Tools.defaultCharset);
                mid.append(temp);
            }
            contenu = debut + mid.toString() + fin;
        }
        return contenu.getBytes(Tools.defaultCharset);
    }

    /**
     * Modifie le contenu pour y introduire les informations des titres d'un disque dans une boucle 'loopTitreA'
     * @param contenuArray le contenu
     * @param titres les titres du disque (face A)
     * @return le contenu modifié
     * @throws VinylManagerException en cas d'erreur
     */
    private static byte[] processContenuTitresA(byte[] contenuArray, List<Titre> titres) throws VinylManagerException {
        String contenu = new String(contenuArray, Tools.defaultCharset);
        while (contenu.contains("<loopTitreA>")) {
            int indexDeb = contenu.indexOf("<loopTitreA>");
            int indexFin = contenu.indexOf("</loopTitreA>");
            if (indexFin < indexDeb) {
                throw new VinylManagerException(Language.getInstance().get("error.export.html.loop.titreA.invalid"));
            }
            String debut = contenu.substring(0, indexDeb);
            String toMod = contenu.substring(indexDeb + 12, indexFin);
            StringBuilder mid = new StringBuilder("");
            String fin = contenu.substring(indexFin + 13);
            for (Titre titre : titres) {
                String temp = toMod;
                temp = temp.replace("%track%", Tools.formatHtml(titre.toString()));
                mid.append(temp);
            }
            contenu = debut + mid.toString() + fin;
        }
        return contenu.getBytes(Tools.defaultCharset);
    }

    /**
     * Modifie le contenu pour y introduire les informations des titres d'un disque dans une boucle 'loopTitreA'
     * @param contenuArray le contenu
     * @param titres les titres du disque (face A)
     * @return le contenu modifié
     * @throws VinylManagerException en cas d'erreur
     */
    private static byte[] processContenuTitresB(byte[] contenuArray, List<Titre> titres) throws VinylManagerException {
        String contenu = new String(contenuArray, Tools.defaultCharset);
        while (contenu.contains("<loopTitreB>")) {
            int indexDeb = contenu.indexOf("<loopTitreB>");
            int indexFin = contenu.indexOf("</loopTitreB>");
            if (indexFin < indexDeb) {
                throw new VinylManagerException(Language.getInstance().get("error.export.html.loop.titreB.invalid"));
            }
            String debut = contenu.substring(0, indexDeb);
            String toMod = contenu.substring(indexDeb + 12, indexFin);
            StringBuilder mid = new StringBuilder("");
            String fin = contenu.substring(indexFin + 13);
            for (Titre titre : titres) {
                String temp = toMod;
                temp = temp.replace("%track%", Tools.formatHtml(titre.toString()));
                mid.append(temp);
            }
            contenu = debut + mid.toString() + fin;
        }
        return contenu.getBytes(Tools.defaultCharset);
    }

    /**
     * Ecrit le contenu du tableau dans un fichier.
     * @param content le contenu à écrire
     * @param f Le fichier dans lequel écrire
     * @throws VinylManagerException en cas d'erreur
     */
    private static void writeFile(byte[] content, File f) throws VinylManagerException {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(f);
            fos.write(content);
        } catch (FileNotFoundException ex) {
            throw new VinylManagerException("error.html.export", ex);
        } catch (IOException ex) {
            throw new VinylManagerException("error.html.export", ex);
        } finally {
            Tools.closeQuietly(fos);
        }
    }
}

/**
 * Classe interne pour un artiste
 * @author Mathieu Syben
 */
class Artiste {

    /**
     * Le numéro incrémental
     */
    private static int nbr = 1;
    /**
     * Le numero d'artiste
     */
    private int nbrArtiste;
    /**
     * Le nom de l'artiste
     */
    private String nom;
    /** Le nom pour le tri */
    private String nomTri;
    /**
     * Les albums de l'artiste
     */
    private List<AlbumExt> albums = new ArrayList<AlbumExt>();

    /**
     * Constructeur
     */
    public Artiste() {
        nbrArtiste = nbr;
    }

    /**
     * Getter pour albums
     * @return albums
     */
    public List<AlbumExt> getAlbums() {
        return albums;
    }

    /**
     * Ajoute un album .
     * @param album L'album à ajouter
     */
    public void addAlbum(Album album) {
        AlbumExt ext = new AlbumExt(album);
        ext.setNbr(nbr);
        nbr++;
        this.albums.add(ext);
    }

    /**
     * Getter pour nom
     * @return nom
     */
    public String getNom() {
        return nom;
    }

    /**
     * Getter pour nbrArtiste
     * @return nbrArtiste
     */
    public int getNbrArtiste() {
        return nbrArtiste;
    }

    /**
     * Setter pour nom.
     * @param nom le nom
     */
    public void setNom(String nom) {
        this.nom = nom;
    }

    /**
     * Remet nbr à 0;
     */
    public static void reset() {
        nbr = 1;
    }



    /**
     * Getter pour nom de tri
     * @return nom de tri
     */
    public String getNomTri() {
        return nomTri;
    }

    /**
     * Setter pour nom de tri.
     * @param nom le nom de tri
     */
    public void setNomTri(String nomTri) {
        this.nomTri = nomTri;
    }
}

/**
 * Classe interne pour un album.
 * @author Mathieu Syben
 */
class AlbumExt implements Comparable {

    /**
     * Le nom du fichier html
     */
    private String htmlName;
    /**
     * Le numéro d'album
     */
    private int nbr;
    /**
     * L'objet album
     */
    private Album album;

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

    /**
     * Getter pour album
     * @return album
     */
    public Album getAlbum() {
        return this.album;
    }

    /**
     * Getter pour nbr
     * @return nbr
     */
    public int getNbr() {
        return nbr;
    }

    /**
     * Setter pour nbr.
     * @param nbr le nombre
     */
    public void setNbr(int nbr) {
        this.nbr = nbr;
        htmlName = ("album" + nbr + ".html");

    }

    /**
     * Retourne le nom du fichier html
     * @return le nom du fichier html
     */
    public String getHtmlName() {
        return htmlName;
    }

    @Override
    public int compareTo(Object o) {
        if (o instanceof AlbumExt) {
            AlbumExt ext = (AlbumExt) o;
            if (this.getAlbum().getAnnee() == null && ext.getAlbum().getAnnee() == null) {
                return this.getAlbum().getTitre().compareTo(ext.getAlbum().getTitre());
            }
            if (this.getAlbum().getAnnee() == null) {
                return -1;
            }
            if (ext.getAlbum().getAnnee() == null) {
                return 1;
            }
            int c1 = this.getAlbum().getAnnee().compareTo(ext.getAlbum().getAnnee());
            if (c1 == 0) {
                return this.getAlbum().getTitre().compareTo(ext.getAlbum().getTitre());
            } else {
                return c1;
            }
        } else {
            return 1;
        }
    }

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

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(this.album.getAnnee()).append(this.album.getTitre()).hashCode();
    }
}
