/*
 * Copyright ©1998-2020 by Richard A. Wilkes. All rights reserved.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, version 2.0. If a copy of the MPL was not distributed with
 * this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This Source Code Form is "Incompatible With Secondary Licenses", as
 * defined by the Mozilla Public License, version 2.0.
 */

package com.trollworks.gcs.utility;

import java.io.File;
import java.io.PrintStream;
import java.text.SimpleDateFormat;
import java.util.Date;

/** Provides standardized logging. */
public class Log {
    private static final String           SEPARATOR = " | ";
    private static final SimpleDateFormat FORMAT    = new SimpleDateFormat("yyyy.MM.dd" + SEPARATOR + "HH:mm:ss.SSS");
    private static       PrintStream      OUT;

    static {
        OUT = System.out;
        String property = Debug.getPropertyOrEnvironmentSetting("GCS_LOG");
        if (property != null && !property.isBlank()) {
            try {
                OUT = new PrintStream(property);
            } catch (Throwable throwable) {
                error("Unable to redirect log to " + property, throwable);
            }
        } else if (Platform.isWindows()) {
            String localAppData = System.getenv("LOCALAPPDATA");
            if (localAppData != null) {
                File logDirectory = new File(localAppData + "\\GCS");
                try {
                    logDirectory.mkdirs();
                    OUT = new PrintStream(logDirectory + "\\error.log");
                } catch (Throwable throwable) {
                    error("Unable to redirect log to " + logDirectory + "\\error.log", throwable);
                }
            }
        }
    }

    /**
     * Logs an error.
     *
     * @param msg The message to log.
     */
    public static final void error(String msg) {
        error(msg, null);
    }

    /**
     * Logs an error.
     *
     * @param throwable The {@link Throwable} to log.
     */
    public static final void error(Throwable throwable) {
        error(null, throwable);
    }

    /**
     * Logs an error.
     *
     * @param msg       The message to log.
     * @param throwable The {@link Throwable} to log.
     */
    public static final void error(String msg, Throwable throwable) {
        post('E', msg, throwable);
    }

    /**
     * Logs a warning.
     *
     * @param msg The message to log.
     */
    public static final void warn(String msg) {
        warn(msg, null);
    }

    /**
     * Logs a warning.
     *
     * @param throwable The {@link Throwable} to log.
     */
    public static final void warn(Throwable throwable) {
        warn(null, throwable);
    }

    /**
     * Logs a warning.
     *
     * @param msg       The message to log.
     * @param throwable The {@link Throwable} to log.
     */
    public static final void warn(String msg, Throwable throwable) {
        post('W', msg, throwable);
    }

    private static void post(char levelCode, String msg, Throwable throwable) {
        StringBuilder buffer = new StringBuilder();
        buffer.append(levelCode);
        buffer.append(SEPARATOR);
        buffer.append(FORMAT.format(new Date()));
        buffer.append(SEPARATOR);
        if (msg != null && !msg.isEmpty()) {
            buffer.append(msg);
        }
        OUT.println(buffer);
        if (throwable != null) {
            throwable.printStackTrace(OUT);
        }
    }
}

@@ -455,21 +455,32 @@
 ort 
-java.io.File;
+com.trollworks.gcs.GCS;%0A
 %0Aimp
@@ -504,16 +504,141 @@
 Stream;%0A
+import java.nio.charset.StandardCharsets;%0Aimport java.nio.file.Files;%0Aimport java.nio.file.Path;%0Aimport java.nio.file.Paths;%0A
 import j
@@ -745,16 +745,84 @@
 s Log %7B%0A
+    private static final String           GCS_LOG_FILE = %22gcs.log%22;%0A
     priv
@@ -865,16 +865,19 @@
 PARATOR 
+   
 = %22 %7C %22;
@@ -929,16 +929,19 @@
 RMAT    
+   
 = new Si
@@ -1086,16 +1086,48 @@
 em.out;%0A
+        Path   path     = null;%0A
         
@@ -1265,60 +1265,249 @@
     
-try %7B%0A                OUT = new PrintStream(property
+path = Paths.get(property);%0A        %7D else if (GCS.VERSION != 0) %7B // When running a dev version, assume the console is always appropriate, since you're likely running from an IDE%0A            String home = System.getProperty(%22user.home%22, %22.%22
 );%0A 
@@ -1521,172 +1521,190 @@
     
-%7D ca
+swi
 tch (
-Throwable throwable) %7B%0A                error(%22Unable to redirect log to %22 + property, throwable);%0A            %7D%0A        %7D else if (Platform.isWindows()) %7B%0A
+Platform.getPlatform()) %7B%0A            case MAC:%0A                path = Paths.get(home, %22Library%22, %22Logs%22, GCS_LOG_FILE);%0A                break;%0A            case WINDOWS:%0A    
     
@@ -1776,19 +1776,36 @@
         
-if 
+    path = Paths.get
 (localAp
@@ -1821,223 +1821,459 @@
 null
-) %7B%0A                File logDirectory = new File(localAppData + %22%5C%5CGCS%22);%0A                try %7B%0A                    logDirectory.mkdirs();%0A                    OUT = new PrintStream(logDirectory + %22%5C%5Cerror.log%22);%0A   
+ ? localAppData : home, %22logs%22, GCS_LOG_FILE);%0A                break;%0A            default:%0A                path = Paths.get(home, %22.local%22, %22logs%22, GCS_LOG_FILE);%0A                break;%0A            %7D%0A        %7D%0A        if (path != null) %7B%0A            try %7B%0A                path = path.normalize().toAbsolutePath();%0A                Files.createDirectories(path.getParent());%0A                OUT = new PrintStream(path.toFile(), StandardCharsets.UTF_8);%0A
     
@@ -2280,17 +2280,16 @@
         
- 
 %7D catch 
@@ -2308,28 +2308,24 @@
 hrowable) %7B%0A
-    
             
@@ -2369,67 +2369,25 @@
 %22 + 
-logDirectory + %22%5C%5Cerror.log%22, throwable);%0A                %7D
+path, throwable);
 %0A   

Change logging defaults again...