// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package adaptorlib;

import java.io.*;
import java.text.MessageFormat;
import java.util.Date;
import java.util.logging.*;

/**
 * Custom log formatter for ease of development. It is specifically targeted to
 * use in console output and is able to produce color output on Unix terminals.
 */
public class CustomFormatter extends Formatter {
  private static final String newline = System.getProperty("line.separator");
  private Date date = new Date();
  // The format for a color is '\x1b[30;40m' where 30 and 40 are the foreground
  // and background colors, respectively. The ';' isn't required. If you don't
  // provide a foreground or background, it will be set to the default.
  private MessageFormat formatter = new MessageFormat(
      "\u001b[3{5}m{0,date,HH:mm:ss.SSS} \u001b[3{6}m{1}\u001b[3{5}m {2} {3}:\u001b[m {4}");
  /** Is identical to {@link #formatter} except for colors */
  private MessageFormat noColorFormatter = new MessageFormat(
      "{0,date,HH:mm:ss.SSS} {1} {2} {3}: {4}");
  private StringBuffer buffer = new StringBuffer();
  private PrintWriter writer = new PrintWriter(new StringBufferWriter(buffer));
  /**
   * Flag for whether color escapes should be used. Defaults to false on
   * Windows and true on all other platforms. Can be overridden with the
   * {@code adaptorlib.CustomFormatter.useColor} logging configuration property.
   */
  private boolean useColor = !System.getProperty("os.name").contains("Windows");
  /**
   * Default highlight color is a cyan on my terminal. This color needs to be
   * readable on both light-on-dark and dark-on-light setups.
   */
  private int highlightColor = 6;
  /** Colors range from 30-37 for foreground and 40-47 for background */
  private final int numberOfColors = 8;

  public CustomFormatter() {
    LogManager manager = LogManager.getLogManager();
    String className = getClass().getName();

    String value = manager.getProperty(className + ".useColor");
    if (value != null) {
      setUseColor(Boolean.parseBoolean(value));
    }
  }

  public synchronized String format(LogRecord record) {
    buffer.delete(0, buffer.length());

    date.setTime(record.getMillis());
    String threadName;
    if (record.getThreadID() == Thread.currentThread().getId()) {
      threadName = Thread.currentThread().getName();
    } else {
      threadName = "" + record.getThreadID();
    }
    // We know that one of the colors is used for the background. The default
    // for terminals is 40, so we avoid using color 30 here.
    int threadColor = (record.getThreadID() % (numberOfColors - 1)) + 1;
    String method = record.getSourceClassName() + "."
        + record.getSourceMethodName() + "()";
    if (method.length() > 30) {
      method = method.substring(method.length() - 30);
    }
    getActiveFormat().format(
        new Object[] {date, threadName, method,
          record.getLevel().getLocalizedName(), formatMessage(record),
          highlightColor, threadColor
        }, buffer, null);
    buffer.append(newline);
    if (record.getThrown() != null) {
      record.getThrown().printStackTrace(writer);
    }

    String formatted = buffer.toString();
    buffer.delete(0, buffer.length());
    return formatted;
  }

  private MessageFormat getActiveFormat() {
    return useColor ? formatter : noColorFormatter;
  }

  public boolean isUseColor() {
    return useColor;
  }

  public void setUseColor(boolean useColor) {
    this.useColor = useColor;
  }

  private static class StringBufferWriter extends Writer {
    private StringBuffer sb;

    public StringBufferWriter(StringBuffer sb) {
      this.sb = sb;
    }

    public void close() {
      sb = null;
    }

    public void flush() throws IOException {
      if (sb == null) {
        throw new IOException("Writer closed");
      }
    }

    public void write(char[] cbuf, int off, int len) throws IOException {
      if (sb == null) {
        throw new IOException("Writer closed");
      }
      sb.append(cbuf, off, len);
    }
  }
}
