package be.msyben.vinylManager.tools.lastfm;

import be.msyben.vinylManager.exceptions.VinylManagerException;
import be.msyben.vinylManager.tools.Tools;
import be.msyben.vinylManager.tools.internalEntities.ImageUrl;
import de.umass.lastfm.Album;
import de.umass.lastfm.ImageSize;
import java.util.*;

/**
 * Permet de s'interfacer avec LastFm pour réupérer des images.
 * @author Mathieu Syben
 */
public final class LastFmInterface {

    /**
     * La cle de connection pour lastFM. Merci de ne pas la diffuser.
     */
    private static final String KEY = "bfafe3b21e89c688dec85cf2f2fecba6";

    /**
     * Les distance de tolérance pour l'artiste et l'album.
     */
    private static final int ARTIST_DISTANCE = 20;
    private static final int ALBUM_DISTANCE = 20;

    /**
     * Constructeur privé pour ne pas instancier.
     */
    private LastFmInterface() {}


    /**
     * Récupère les image liées aux informations de l'album.
     * @param albumName le nom de l'album
     * @param artistName le titre de l'album
     * @return une liste d'images.
     */
    public static List<ImageUrl> getImages(String albumName, String artistName) throws VinylManagerException {
        List<ImageUrl> ret = new ArrayList<ImageUrl>();
        for (String url : getUrls(albumName, artistName)) {
            byte[] contenu = Tools.downloadFile(url);
            if (contenu != null && contenu.length > 0) {
                ImageUrl img = new ImageUrl();
                byte[] contenuResized = Tools.convertToRGB(contenu);
                if (contenuResized != null && contenuResized.length > 0) {
                    img.setContenu(contenuResized);
                } else{
                    img.setContenu(contenu);
                }
                
                String[] spl = url.split("/");
                img.setNom(spl[spl.length-1]);
                img.setUrl(url);
                ret.add(img);
            }
        }
        return ret;
    }

    /**
     * Récupère les urls des images susceptibles d'etre celles de l'album passe en parametre.
     * @param albumName le nom de l'album
     * @param artistName le nom de l'artiste
     * @return la liste des urls des images.
     */
    private static Set<String> getUrls(String albumName, String artistName) {
        Set<String> ret = new HashSet<String>();

        boolean needMoreUrl = false;

        Album alb = Album.getInfo(artistName, albumName, KEY);

        if (alb != null) {
            String url = getLargestImageUrl(alb);
            if (url != null) {
                ret.add(url);
            } else {
                needMoreUrl = true;
            }
        } else {
            needMoreUrl = true;
        }

        if (needMoreUrl) {
            Collection<Album> search = Album.search(albumName, KEY);
            for (Album albumSearch : search) {
                int artDist = Tools.distance(albumSearch.getArtist(), artistName);
                int albDist = Tools.distance(albumSearch.getName(), albumName);
                if ( artDist < ARTIST_DISTANCE &&
                        albDist < ALBUM_DISTANCE) {
                    String url = getLargestImageUrl(albumSearch);
                    if (url != null) {
                        ret.add(url);
                    }
                }
            }
        }

        return ret;
    }


    /**
     * Récupère la plus grande image d'un album.
     * @param alb l'album
     * @return l'url de la plus grande image. Null si pas d'image.
     */
    private static String getLargestImageUrl(Album alb) {
        ImageSize lastIs = null;
        String url = null;
        for (ImageSize is : alb.availableSizes()) {
            String urlIn = alb.getImageURL(is);
            if (urlIn != null && urlIn.length() > 0) {
                if (url == null) {
                    url = urlIn;
                    lastIs = is;
                } else {
                    if (compareIS(is, lastIs)) {
                        url = urlIn;
                        lastIs = is;
                    }
                }
            }
        }
        if (url == null || url.length() == 0) {
            return null;
        }
        return url;
    }

    /**
     * Renvoie true si is1 > is2
     * @param is1 le premier ImageSize
     * @param is2 le second ImageSize
     * @return true si is1 > is2; false sinon
     */
    private static boolean compareIS(ImageSize is1, ImageSize is2) {

        if (is1.equals(ImageSize.SMALL)) {
            return false;
        }
        if (is1.equals(ImageSize.MEDIUM)) {
            return is2.equals(ImageSize.SMALL);
        }
        if (is1.equals(ImageSize.LARGE)) {
            return is2.equals(ImageSize.SMALL) || is2.equals(ImageSize.MEDIUM);
        }
        if (is1.equals(ImageSize.LARGESQUARE)) {
            return is2.equals(ImageSize.SMALL) || is2.equals(ImageSize.MEDIUM) || is2.equals(ImageSize.LARGE);
        }
        if (is1.equals(ImageSize.HUGE)) {
            return is2.equals(ImageSize.SMALL) || is2.equals(ImageSize.MEDIUM) || is2.equals(ImageSize.LARGE) || is2.equals(ImageSize.LARGESQUARE);
        }
        if (is1.equals(ImageSize.EXTRALARGE)) {
            return is2.equals(ImageSize.SMALL) || is2.equals(ImageSize.MEDIUM) || is2.equals(ImageSize.LARGE) || is2.equals(ImageSize.LARGESQUARE) || is2.equals(ImageSize.HUGE);
        }
        if (is1.equals(ImageSize.MEGA)) {
            return is2.equals(ImageSize.SMALL) || is2.equals(ImageSize.MEDIUM) || is2.equals(ImageSize.LARGE) || is2.equals(ImageSize.LARGESQUARE) || is2.equals(ImageSize.HUGE) || is2.equals(ImageSize.EXTRALARGE);
        }
        if (is1.equals(ImageSize.ORIGINAL)) {
            return true;
        }

        return true;
    }
}
