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.Titre;
import be.msyben.vinylManager.exceptions.VinylManagerException;
import be.msyben.vinylManager.gui.MainWindow;
import be.msyben.vinylManager.properties.Language;
import be.msyben.vinylManager.tools.Sort;
import be.msyben.vinylManager.tools.Tools;
import be.msyben.vinylManager.tools.discogs.DiscogsSearch;
import com.opencsv.CSVReader;
import com.opencsv.exceptions.CsvValidationException;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;

/**
 * Classe permettant d'importer un fichier Csv. CE fichier peut soit être un
 * export VM, soit un export Discogs. Le format VM : titre artiste compositeur
 * reference editeur annee pays chef orchestre musiciens etat commentaire cote
 * genre valeur support parolier date achat compilation num etat taille vitesse
 * couleur canaux A|B num nom duree artiste annee
 *
 * @author Mathieu Syben
 */
public final class CsvImport {

    /**
     * Le séparateur.
     */
    private static final char SEPARATOR = ';';

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

    /**
     * Importe une collection depuis un fichier csv.
     *
     * @param f Le fichier csv.
     * @return La collection importée depuis le fichier.
     * @throws VinylManagerException En cas d'erreur.
     */
    public static Collection importCsv(File f) throws VinylManagerException {

        try {
            byte[] content = Tools.readFile(f);
            String contentStr = new String(content, Tools.defaultCharset);
            //List<String> lines = IOUtils.readLines(is);
            if (contentStr == null || contentStr.isEmpty()) {
                return new Collection();
            }
            
            String[] lines = contentStr.split("\\r?\\n");
            
            
            String line1 = lines[0];
            if (line1.startsWith("Catalog#,Artist,Title,Label,Format,Rating,Released,release_id,CollectionFolder")) {
                //return importCsvDiscogs(lines.subList(1, lines.size()));
                return importCsvDiscogs(f);
            } else {
                //return importCsvVm(lines);
                throw new VinylManagerException(Language.getInstance().get("csv.import.error"));
            }
        } catch (IOException ex) {
            throw new VinylManagerException(Language.getInstance().get("csv.import.error"), ex);
        } 

    }

    private static Collection importCsvDiscogs(File f) throws VinylManagerException {
        Collection c = new Collection();

        Reader r = null;
        CSVReader reader = null;

        long albumId = 0L;
        long lineId = 0L;
        try {
            r = new FileReader(f);
            reader = new CSVReader(r);
            String[] nextLine;
            while ((nextLine = reader.readNext()) != null) {
                lineId++;
                if (nextLine.length >= 8) {
                    String id = nextLine[7];
                    try {
                        int parseId = Integer.parseInt(id);
                        System.out.println("Ligne " + lineId + ". Besoin de téléchargement Discogs pour import csv : " + id);
                        //System.out.println(",,,,,," + id);
                        Album a = DiscogsSearch.getAlbum(parseId, MainWindow.getInstance());
                        if (a != null) {
                            a.setId(albumId);
                            albumId++;
                            c.getAlbums().add(a);
                        } else {
                            System.err.println("Erreur de téléchargement Discogs pour import csv : " + id);
                        }
                    } catch (NumberFormatException ex) {
                        System.err.println("Erreur de parsing dans la ligne " + lineId + ". " + id + " ne peut pas être utilisé pour récupérer un album dans Discogs.");
                    } catch (VinylManagerException ex) {
                        System.err.println("Erreur de la récupération de l'album " + id);
                    }
                }
            }
        } catch (IOException | CsvValidationException ex) {
            throw new VinylManagerException(Language.getInstance().get("csv.import.error"), ex);
        } finally {
            Tools.closeQuietly(reader);
            Tools.closeQuietly(r);
        }


        return c;
    }

    private static Collection importCsvDiscogs(List<String> lines) throws VinylManagerException {
        Collection c = new Collection();

        long albumId = 0L;
        long lineId = 0L;
        for (String line : lines) {
            lineId++;
            String[] spl = line.split(",");
            boolean guillemet = false;
            String current = "";
            List<String> cond = new ArrayList<String>();
            for (String token : spl) {
                if (guillemet) {
                    current += token;
                    if (token.endsWith("\"")) {
                        cond.add(current);
                        current = "";
                        guillemet = false;
                    }
                } else {
                    if (token.startsWith("\"")) {
                        current = token;
                        guillemet = true;
                    } else {
                        cond.add(token);
                    }
                }
            }

            if (cond.size() >= 8) {
                String id = cond.get(7);
                try {
                    int parseId = Integer.parseInt(id);
                    //System.out.println("Ligne " + lineId + ". Besoin de téléchargement Discogs pour import csv : " + id);
                    Album a = DiscogsSearch.getAlbum(parseId, MainWindow.getInstance());
                    if (a != null) {
                        a.setId(albumId);
                        albumId++;
                        c.getAlbums().add(a);
                    } else {
                        System.err.println("Erreur de téléchargement Discogs pour import csv : " + id);
                    }
                } catch (NumberFormatException ex) {
                    System.err.println("Erreur de parsing dans la ligne " + lineId + ". " + id + " ne peut pas être utilisé pour récupérer un album dans Discogs.");
                } catch (VinylManagerException ex) {
                    System.err.println("Erreur de la récupération de l'album " + id);
                }
            } else {
                System.err.println("La ligne " + lineId + " ne peut pas être traitée. " + line);
            }
        }
        return c;
    }

    /*private static Collection importCsvVm(String[] lines) throws VinylManagerException {

        List<CsvImportData> data = new ArrayList<CsvImportData>();
        for (String line : lines) {
            if (line != null && line.length() > 0) {
                data.add(new CsvImportData(line, SEPARATOR));
            }
        }

        Sort.sort(data, "artiste", "titre", "annee", "disqueNumero", "face", "numeroPiste");

        Collection c = new Collection();

        String lastArtist = "";
        String lastTitre = "";
        String lastAnnee = "";
        int lastDiscNum = 0;
        Album album = null;
        Disque disque = null;

        long albumId = 0L;

        for (CsvImportData cid : data) {
            if (!(cid.getArtiste().equals(lastArtist)) || !(cid.getTitre().equals(lastTitre)) || !(cid.getAnnee().equals(lastAnnee))) {
                // nouveau album
                if (album != null) {
                    if (disque != null) {
                        try {
                            album.addDisque(disque.clone());
                        } catch (CloneNotSupportedException ex) {
                        }
                    }
                    try {
                        album.setId(albumId);
                        c.setLastId(albumId);
                        albumId++;
                        c.getAlbums().add(album.clone());
                    } catch (CloneNotSupportedException ex) {
                    }
                }

                album = new Album();
                album.setTitre(cid.getTitre());
                lastTitre = cid.getTitre();
                album.setArtiste(cid.getArtiste());
                lastArtist = cid.getArtiste();
                album.setAnnee(cid.getAnnee());
                lastAnnee = cid.getAnnee();
                album.setAnneeParution(cid.getAnneeParution());
                album.setPays(cid.getPays());
                album.setCompositeur(cid.getCompositeur());
                album.setReference(cid.getReference());
                album.setEditeur(cid.getEditeur());
                album.setChef(cid.getChef());
                album.setOrchestre(cid.getOrchestre());
                album.setMusiciens(prepare(cid.getMusiciens()));
                album.setEtat(cid.getEtat());
                album.setCommentaire(prepare(cid.getCommentaire()));
                album.setCote(cid.getCote());
                album.setCoteDemi(cid.getCoteDemi());
                album.setGenre(cid.getGenre());
                album.setValeur(cid.getValeur());
                album.setSupport(cid.getSupport());
                album.setCompilation(cid.isCompilation());
                album.setParolier(cid.getParolier());
                album.setLocation(cid.getLocation());
                album.setPossede(cid.getPossede());
                album.setDateAchat(cid.getDateAchat());
                disque = null;
                lastDiscNum = 0;
            }
            if (cid.isHasDisques()) {
                if (lastDiscNum != cid.getDisqueNumero()) {
                    // nouveau disque
                    if (disque != null) {
                        try {
                            album.addDisque(disque.clone());
                        } catch (CloneNotSupportedException ex) {
                        }
                    }
                    disque = new Disque();
                    lastDiscNum = cid.getDisqueNumero();
                    disque.setNum(lastDiscNum);
                    disque.setEtat(cid.getDisqueEtat());
                    disque.setTaille(cid.getTaille());
                    disque.setVitesse(cid.getVitesse());
                    disque.setCouleur(cid.getCouleur());
                    disque.setCanaux(cid.getCanaux());
                }
                Titre t = new Titre();
                t.setNum(cid.getNumeroPiste());
                t.setAnnee(cid.getAnneePiste());
                t.setArtiste(cid.getArtistePiste());
                t.setDuree(cid.getDureePiste());
                t.setNom(cid.getNomPiste());
                if (cid.getFace().equals("a")) {
                    disque.getFaceA().add(t);
                } else {
                    disque.getFaceB().add(t);
                }
            }
        }
        if (album != null) {
            if (disque != null) {
                album.addDisque(disque);
            }
            album.setId(albumId);
            c.setLastId(albumId);
            albumId++;
            try {
                c.getAlbums().add(album.clone());
            } catch (CloneNotSupportedException ex) {
            }
        }

        return c;
    }*/

    /**
     * Prepare un string
     *
     * @param s le String à préparer.
     * @return Le string à remettre dans la collection
     */
    private static String prepare(String s) {
        if (s == null) {
            return "";
        }
        String ret = s;
        ret = ret.replace("\\r", "\r");
        ret = ret.replace("\\n", "\n");
        return ret;
    }
}
