package be.msyben.vinylManager.tools.log;

import be.msyben.vinylManager.tools.Tools;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Opérations de logs pour VinylManager
 *
 * @author Mathieu Syben
 */
public final class VinylManagerLogger {

    private static final StringBuilder sb = new StringBuilder();
    private static final File logFile;
    private static final File logDir;
    private static final DateFormat df = new SimpleDateFormat("dd/M/yyyy HH:mm:ss_SSS");
    private static final Timer writeTimer = new Timer(true);

    static {
        logDir = new File(System.getProperty("user.home", "/temp"),".vm_logs");
        if (!(logDir.exists() && logDir.isDirectory())) {
            logDir.mkdir();
        }
        logFile = new File(logDir, "VM_" + System.currentTimeMillis() + ".log");

        TimerTask myTT = new TimerTask() {
            @Override
            public void run() {
                VinylManagerLogger.writeLogToFile();
            }
        };
        writeTimer.scheduleAtFixedRate(myTT, 1000L, 10L * 1000L);
    }

    private VinylManagerLogger() {
    }

    /**
     * Logge un texte.
     * @param text Le texte à logger.
     */
    public static synchronized void log(String text) {
        sb.append(getCallTime()).append(" - ").append(getCaller()).append(" - ").append(text).append("\r\n");
    }

    /**
     * Logge un texte et une exception.
     * @param text Le texte à logger.
     * @param exception L'exception à logger.
     */
    public static synchronized void log(String text, Throwable exception) {
        sb.append(getCallTime()).append(" - ").append(getCaller()).append(" - ").append(text).append("\r\n");
        sb.append(Tools.getStackTrace(exception)).append("\r\n");
    }

    /**
     * Logge une exception.
     * @param exception L'exception à logger.
     */
    public static synchronized void log(Throwable exception) {
        sb.append(getCallTime()).append(" - ").append(getCaller()).append(" - ").append(Tools.getStackTrace(exception)).append("\r\n");
    }
    
    protected static synchronized void logFromOut(String log) {
        sb.append(getCallTime()).append(" - ").append(log).append("\r\n");
    }
    
    protected static synchronized void logFromOut(int i) {
        sb.append((char)i);
    }

    private static String getCallTime() {
        return df.format(new Date());
    }

    private static String getCaller() {
        StackTraceElement ste = Thread.currentThread().getStackTrace()[3];
        return ste.getClassName() + ":" + ste.getMethodName() + ":" + ste.getLineNumber();
    }

    /**
     * Permet d'écrire le contenu du log dans un fichier.
     */
    public static synchronized void writeLogToFile() {
        String toWrite = sb.toString();
        if (toWrite.length() > 0) System.out.println(toWrite);
        sb.delete(0, sb.length());
        FileWriter fstream = null;
        BufferedWriter out = null;
        try {
            fstream = new FileWriter(logFile, true);
            out = new BufferedWriter(fstream);
            out.write(toWrite);
        } catch (IOException ex) {
            sb.append(toWrite);
            log(ex);
        } finally {
            Tools.closeQuietly(out);
            Tools.closeQuietly(fstream);
        }
    }

    /**
     * Supprime les fichier de logs plus vieux que 1 mois.
     */
    public static synchronized void deleteOldLogFiles() {
        File[] logs = logDir.listFiles();
        long old = System.currentTimeMillis() - (1L*31L*24L*60L*60L*1000L);
        log("Suppression des fichiers de logs < " + old);
        for (File log : logs) {
            String logName = log.getName();
            if (logName.startsWith("VM_") && logName.endsWith(".log")) {
                logName = logName.substring(3, logName.length() - 4);
                try {
                    long logTime = Long.parseLong(logName);
                    if (logTime < old) {
                        log("Suppression de " + logName);
                        if (!log.delete()) {
                            log.deleteOnExit();
                        }
                    }
                } catch (NumberFormatException ex) {
                }
            }
        }
    }

    /**
     * Fin.
     */
    public static synchronized void exit() {
        log("Fermeture");
        writeTimer.cancel();
        writeLogToFile();
    }
}
