/*
 * ====================================================================
 * Copyright (c) 2004 TMate Software Ltd. All rights reserved.
 * 
 * This software is licensed as described in the file COPYING, which you should
 * have received as part of this distribution. The terms are also available at
 * http://tmate.org/svn/license.html. If newer versions of this license are
 * posted there, you may use a newer version instead, at your option.
 * ====================================================================
 */
package org.tmatesoft.svn.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

/**
 * @version 1.0
 * @author TMate Software Ltd.
 */
public class DebugDefaultLogger implements DebugLogger, LoggingStreamLogger {

    private static final DateFormat ourDateFormat = new SimpleDateFormat(
            "yyyy-MM-dd' 'HH:mm:ss.SSS");

	static {
		try {
			Logger.getLogger("svn").setUseParentHandlers(false);
			SimpleFormatter f = new SimpleFormatter() {
				public synchronized String format(LogRecord record) {
					StringBuffer sb = new StringBuffer();
					String message = formatMessage(record);
					sb.append(ourDateFormat
							.format(new Date(record.getMillis())));
					sb.append(": ");
					sb.append(message);
					sb.append(System.getProperty("line.separator"));
					if (record.getThrown() != null) {
						try {
							StringWriter sw = new StringWriter();
							PrintWriter pw = new PrintWriter(sw);
							record.getThrown().printStackTrace(pw);
							pw.close();
							sb.append(sw.toString());
						} catch (Exception e) {
						}
					}
					return sb.toString();
				}
			};
			String levelStr = System.getProperty("javasvn.log.level", "OFF");
			Level level = Level.parse(levelStr);
			if (isFileLoggingEnabled()) {
				String path = System.getProperty("javasvn.log.path");
				if (path == null) {
					path = "%home%/.javasvn/.javasvn.%g.%u.log";
				}
				path = path.replace(File.separatorChar, '/');
				path = path.replaceAll("%home%", System
						.getProperty("user.home").replace(File.separatorChar,
								'/'));
				path = path.replace('/', File.separatorChar);
				File dir = new File(path).getParentFile();
				if (!dir.exists()) {
					dir.mkdirs();
				}

                Handler handler = new FileHandler(path, 1024 * 1024, 10, true);
                handler.setFormatter(f);
                handler.setLevel(level);
                Logger.getLogger("svn").addHandler(handler);
            }
            if (Boolean.getBoolean("javasvn.log.console")) {
                ConsoleHandler cHandler = new ConsoleHandler();
                cHandler.setLevel(level);
                cHandler.setFilter(null);
                cHandler.setFormatter(f);
                Logger.getLogger("svn").addHandler(cHandler);
            }
            Logger.getLogger("svn").setLevel(level);
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public boolean isFineEnabled() {
        return true;
    }

    public void logFine(String message) {
        Logger.getLogger("svn").log(Level.FINE, message);
    }

    public boolean isInfoEnabled() {
        return true;
    }

    public void logInfo(String message) {
        Logger.getLogger("svn").log(Level.INFO, message);
    }

    public boolean isErrorEnabled() {
        return true;
    }

    public void logError(String message, Throwable th) {
        if (th == null) {
            Logger.getLogger("svn").log(Level.SEVERE, message);
        } else {
            Logger.getLogger("svn").log(Level.SEVERE, message, th);
        }
    }

    public LoggingInputStream getLoggingInputStream(String protocol,
            InputStream stream) {
        protocol = protocol == null ? "svn" : protocol;
        final boolean enabled = Boolean.getBoolean("javasvn.log." + protocol);
        return new LoggingInputStream(stream, enabled ? this : null);
    }

    public LoggingOutputStream getLoggingOutputStream(String protocol,
            OutputStream stream) {
        protocol = protocol == null ? "svn" : protocol;
        final boolean enabled = Boolean.getBoolean("javasvn.log." + protocol);
        return new LoggingOutputStream(stream, enabled ? this : null);
    }

    public void logStream(String content, boolean writeNotRead) {
        final String prefix = writeNotRead ? "SVN.SENT: " : "SVN.READ: ";
        content = content.replaceAll("\n", "\\\\n");
        content = content.replaceAll("\r", "\\\\r");
        logFine(prefix + content);
    }

    private static boolean isFileLoggingEnabled() {
        if (System.getProperty("javasvn.log.file") == null) {
            return true;
        }
        return Boolean.getBoolean("javasvn.log.file");
    }
}