package be.msyben.vinylManager.tools;

import be.msyben.vinylManager.VinylManager;
import be.msyben.vinylManager.properties.Language;
import be.msyben.vinylManager.properties.Preferences;
import be.msyben.vinylManager.tools.log.VinylManagerLogger;
import be.msyben.vinylManager.tools.swing.JLink;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.Response;
import java.awt.BorderLayout;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

/**
 * Cette classe vérifie que la verison en cours est la dernière.
 *
 * @author Mathieu Syben
 */
public class VersionChecker extends Thread {

    /**
     * URL du fichier contenant le numéro de la dernière version.
     */
    private static final String url = "https://www.msyben.be/vinylManager/lastVersion.txt";
    
    /**
     * Version courante (lue depuis le fichier généré par maven).
     */
    public static final String currentVersion = getCurrentVersion();

    /**
     * Lance le traitement
     */
    @Override
    public void run() {
        if (Preferences.getInstance().get(Preferences.LAST_VERSION_CHECK, "Y").equals("Y")) {
            try {
                //String last = new String(Tools.downloadFile(url), Tools.defaultCharset);
                String last = getLastVersion();
                VinylManagerLogger.log("Dernière version : " + last);
                VinylManagerLogger.log("Version courante : " + VinylManager.version);
                if (last != null && ! last.isEmpty()) {
                    int comp = compareVersion(VinylManager.version, last);
                    if (comp == -1) {
                        String message = Language.getInstance().get("new.version").replace("%1", last);

                        JPanel p = new JPanel(new BorderLayout());
                        p.add(new JLabel(message), BorderLayout.NORTH);
                        p.add(new JLink(Language.getInstance().get("new.version.link.name"), Language.getInstance().get("new.version.link")), BorderLayout.WEST);

                        JOptionPane.showMessageDialog(null, p);
                    }
                }
            } catch (Exception ex) {
                VinylManagerLogger.log(ex);

            }
        }
    }
    
    
    private static String getLastVersion() {
        Client client = ClientBuilder.newClient();
        WebTarget target = client.target(url);
        try {
            Response resp = target.request().get();
            int respStatus = resp.getStatus();
            if (respStatus == 200) {
                return resp.readEntity(String.class);
            } else {                    
                VinylManagerLogger.log( "Mauvais statut de réponse de check de version:" + respStatus);
                return "unknown version";
            }
        } catch (Exception ex) {
            VinylManagerLogger.log("Erreur lors de la récupération de la version", ex);
            return "unknown version";
        }
    }

    /**
     * Compare les 2 versions passées en paramètre.
     *
     * @param currentVersion version de l'application courante
     * @param serverVersion version de la dernière version sur le serveur
     * @return 0 si les versions sont identiques, 1 si la version courante
     * supérieure version du serveur, -1 si version courante inférieure version
     * du serveur
     */
    private static int compareVersion2(String currentVersion, String serverVersion) {
        if (currentVersion.equals(serverVersion)) {
            return 0;
        }

        String[] current = currentVersion.split("[.]");
        String[] server = serverVersion.split("[.]");

        int maxId = Math.min(current.length, server.length);
        int curId = 0;
        while (curId < maxId) {

            int currentInt = Integer.parseInt(current[curId]);
            int serverInt = Integer.parseInt(server[curId]);

            if (currentInt < serverInt) {
                return -1;
            }
            if (currentInt > serverInt) {
                return 1;
            }

            curId++;
        }

        if (current.length == maxId) {
            return -1;
        } else {
            return 1;
        }
    }

    /**
     * Compare les 2 versions passées en paramètre. Prend en compte le beta
     *
     * @param currentVersion version de l'application courante
     * @param serverVersion version de la dernière version sur le serveur
     * @return 0 si les versions sont identiques, 1 si la version courante
     * supérieure version du serveur, -1 si version courante inférieure version
     * du serveur
     */
    private static int compareVersion(String currentVersion, String serverVersion) {
        List<Integer> current = split(currentVersion);
        List<Integer> server = split(serverVersion);
        
        int max = current.size();
        if (server.size() < max) {
            max = server.size();
        }
        
        for (int i = 0; i < max; i++) {
            System.out.println("Comparaison de " + current.get(i) + " et " + server.get(i));
            if (current.get(i) > server.get(i)) {
                return 1;
            } else if (current.get(i) < server.get(i)) {
                return -1;
            }
        }
        
        if (current.size() == server.size()) {
            return 0;
        }
        if (current.size() > server.size()) {
            return 1;
        }
        return -1;
        
    }
    
    private static List<Integer> split(String s) {
        List<Integer> ret = new ArrayList<>();
        
        int currentNum = 0;
        for (char c : s.toCharArray()) {
            if (c == '.') {
                ret.add(currentNum);
                currentNum = 0;
            } else if (c >= '0' && c <= '9') {
                currentNum *= 10;
                currentNum += (c - '0');
            }
        }
        
        ret.add(currentNum);
        
        return ret;
    }
    
    private static int compareVersion3(String currentVersion, String serverVersion) {

        if (currentVersion.equals(serverVersion)) {
            return 0;
        }

        if (currentVersion.contains("-beta")) {
            if (serverVersion.contains("-beta")) {
                // LES 2 SONT EN BETA
                String[] splitCurrent = currentVersion.split("-beta");
                String[] splitServer = serverVersion.split("-beta");
                int compare = compareVersion2(splitCurrent[0], splitServer[0]);
                if (compare == 0) {
                    int serverVersionBeta = Integer.parseInt(splitServer[1]);
                    int currentVersionBeta = Integer.parseInt(splitCurrent[1]);
                    if (currentVersionBeta == serverVersionBeta) {
                        return 0;
                    }
                    if (currentVersionBeta > serverVersionBeta) {
                        return 1;
                    }
                    return -1;
                } else {
                    return compare;
                }
            } else {
                // CURRENT EN BETA ET SERVER EN NON BETA
                String[] splitCurrent = currentVersion.split("-beta");
                int compare = compareVersion2(splitCurrent[0], serverVersion);
                if (compare == 0) {
                    return -1;
                } else {
                    return compare;
                }
            }
        } else {
            if (serverVersion.contains("-beta")) {
                // CURRENT EN NON BETA ET SERVER EN BETA
                String[] splitServer = serverVersion.split("-beta");
                int compare = compareVersion2(currentVersion, splitServer[0]);
                if (compare == 0) {
                    return 1;
                } else {
                    return compare;
                }
            } else {
                // 2 EN NORMAL
                return compareVersion2(currentVersion, serverVersion);
            }
        }
    }
    
    
    /**
     * Récupère la version courante. Soit déjà lue dans le fichier généré par maven et renvoyée directement, soit lecture du fichier.
     * @return la version courante.
     */
    private static synchronized String getCurrentVersion() {
        InputStream is = null;
        ByteArrayOutputStream baos = null;
        try {
            is = VersionChecker.class.getResourceAsStream("/version");
            baos = new ByteArrayOutputStream();
            Tools.copy(is, baos);
            byte[] content = baos.toByteArray();
            String version = new String(content, Tools.defaultCharset);
            return version;
        } catch (IOException e) {
            VinylManagerLogger.log("Erreur lors de la récupération de la version", e);
            return "unknown version";
        } finally {
            Tools.closeQuietly(is);
            Tools.closeQuietly(baos);
        }
    }
}
