/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.log4j.lf5.util;

import org.apache.log4j.lf5.LogLevel;
import org.apache.log4j.lf5.LogRecord;
import org.apache.log4j.lf5.viewer.LogBrokerMonitor;

import java.awt.*;
import java.util.Arrays;
import java.util.List;

/**
 * <p>LogMonitorAdapter facilitates the usage of the LogMonitor</p>
 *
 * @author Richard Hurst
 */

// Contributed by ThoughtWorks Inc.

public class LogMonitorAdapter {
  //--------------------------------------------------------------------------
  //   Constants:
  //--------------------------------------------------------------------------
  public static final int LOG4J_LOG_LEVELS = 0;
  public static final int JDK14_LOG_LEVELS = 1;
  //--------------------------------------------------------------------------
  //   Protected Variables:
  //--------------------------------------------------------------------------

  //--------------------------------------------------------------------------
  //   Private Variables:
  //--------------------------------------------------------------------------
  private LogBrokerMonitor _logMonitor;
  private LogLevel _defaultLevel = null;

  //--------------------------------------------------------------------------
  //   Constructors:
  //--------------------------------------------------------------------------
  private LogMonitorAdapter(List userDefinedLevels) {
    super();
    // set the default level to be the first entry in the list
    _defaultLevel = (LogLevel) userDefinedLevels.get(0);
    _logMonitor = new LogBrokerMonitor(userDefinedLevels);

    _logMonitor.setFrameSize(getDefaultMonitorWidth(),
        getDefaultMonitorHeight());
    _logMonitor.setFontSize(12);
    _logMonitor.show();
  }
  //--------------------------------------------------------------------------
  //   Public Methods:
  //--------------------------------------------------------------------------
  /**
   * <p>Creates an instance of LogMonitorAdapter using the
   * log levels inticated by the parameter. Log4J and JDK1.4 both have default
   * LogLevels which are set but these levels can be overriden.<p>
   *
   * @param loglevels An integer representing either Log4J or JDK1.4 logging levels
   * @return LogMonitorAdapter
   */
  public static LogMonitorAdapter newInstance(int loglevels) {
    LogMonitorAdapter adapter;
    if (loglevels == JDK14_LOG_LEVELS) {
      adapter = newInstance(LogLevel.getJdk14Levels());
      adapter.setDefaultLevel(LogLevel.FINEST);
      adapter.setSevereLevel(LogLevel.SEVERE);
    } else {
      adapter = newInstance(LogLevel.getLog4JLevels());
      adapter.setDefaultLevel(LogLevel.DEBUG);
      adapter.setSevereLevel(LogLevel.FATAL);
    }
    return adapter;
  }

  /**
   * <p>Creates an instance of LogMonitorAdapter using the specified LogLevels.
   * The first LogLevel in the array is used as the default LogLevel unless
   * changed using the setDefaultLevel method.<p>
   *
   * @param userDefined An array of user defined LogLevel objects.
   * @return LogMonitorAdapter
   */
  public static LogMonitorAdapter newInstance(LogLevel[] userDefined) {
    if (userDefined == null) {
      return null;
    }
    return newInstance(Arrays.asList(userDefined));
  }

  /**
   * <p>Creates an instance of LogMonitorAdapter using the specified LogLevels.
   * The first LogLevel in the List is used as the default LogLevel unless
   * changed using the setDefaultLevel method.<p>
   *
   * @param userDefinedLevels A list of user defined LogLevel objects.
   * @return LogMonitorAdapter
   */
  public static LogMonitorAdapter newInstance(List userDefinedLevels) {
    return new LogMonitorAdapter(userDefinedLevels);
  }

  /**
   * <p>Adds a LogRecord to the LogMonitor.<p>
   *
   * @param record The LogRecord object to be logged in the logging monitor.
   */
  public void addMessage(LogRecord record) {
    _logMonitor.addMessage(record);
  }

  /**
   * <p>Set the maximum number of records to be displayed in the monitor<p>
   *
   * @param maxNumberOfRecords
   */
  public void setMaxNumberOfRecords(int maxNumberOfRecords) {
    _logMonitor.setMaxNumberOfLogRecords(maxNumberOfRecords);
  }

  /**
   * <p>Set the default log level to be used when logging messages without
   * specifying a LogLevel.<p>
   *
   * @param level
   */
  public void setDefaultLevel(LogLevel level) {
    _defaultLevel = level;
  }

  /**
   * <p>Gets the default LogLevel for the Adapter.<p>
   *
   * @return LogLevel
   */
  public LogLevel getDefaultLevel() {
    return _defaultLevel;
  }

  /**
   * <p>Sets the Severe LogLevel.</p>
   *
   * @param level
   */
  public void setSevereLevel(LogLevel level) {
    AdapterLogRecord.setSevereLevel(level);
  }

  /**
   * <p>Gets the current Severe LogLevel <p>
   *
   * @return LogLevel
   */
  public LogLevel getSevereLevel() {
    return AdapterLogRecord.getSevereLevel();
  }

  /**
   * <p>Log a complete message to the Monitor.<p>
   *
   * @param category The category to be used
   * @param level The log level to apply to the message
   * @param message The message
   * @param t The throwable content of the message
   * @param NDC The NDC really only applies to Log4J and the parameter can
   *            usually be ignored.
   */
  public void log(String category, LogLevel level, String message,
      Throwable t, String NDC) {
    AdapterLogRecord record = new AdapterLogRecord();
    record.setCategory(category);
    record.setMessage(message);
    record.setNDC(NDC);
    record.setThrown(t);

    if (level == null) {
      record.setLevel(getDefaultLevel());
    } else {
      record.setLevel(level);
    }

    addMessage(record);
  }

  /**
   * <p>Log a message to the Monitor and use the default LogLevel.<p>
   *
   * @param category The category to be used
   * @param message The message
   */
  public void log(String category, String message) {
    log(category, null, message);
  }

  /**
   * <p>Log a message to the Monitor.<p>
   *
   * @param category The category to be used
   * @param level The log level to apply to the message
   * @param message The message
   * @param NDC
   */
  public void log(String category, LogLevel level, String message, String NDC) {
    log(category, level, message, null, NDC);
  }

  /**
   * <p>Log a message to the Monitor.<p>
   *
   * @param category The category to be used
   * @param level The log level to apply to the message
   * @param message The message
   * @param t The throwable content of the message
   */
  public void log(String category, LogLevel level, String message,
      Throwable t) {
    log(category, level, message, t, null);
  }

  /**
   * <p>Log a message to the Monitor.<p>
   *
   * @param category The category to be used
   * @param level The log level to apply to the message
   * @param message The message
   */
  public void log(String category, LogLevel level, String message) {
    log(category, level, message, null, null);
  }

  //--------------------------------------------------------------------------
  //   Protected Methods:
  //--------------------------------------------------------------------------
  /**
   * @return the screen width from Toolkit.getScreenSize()
   * if possible, otherwise returns 800
   * @see java.awt.Toolkit
   */
  protected static int getScreenWidth() {
    try {
      return Toolkit.getDefaultToolkit().getScreenSize().width;
    } catch (Throwable t) {
      return 800;
    }
  }

  /**
   * @return the screen height from Toolkit.getScreenSize()
   * if possible, otherwise returns 600
   * @see java.awt.Toolkit
   */
  protected static int getScreenHeight() {
    try {
      return Toolkit.getDefaultToolkit().getScreenSize().height;
    } catch (Throwable t) {
      return 600;
    }
  }

  protected static int getDefaultMonitorWidth() {
    return (3 * getScreenWidth()) / 4;
  }

  protected static int getDefaultMonitorHeight() {
    return (3 * getScreenHeight()) / 4;
  }
  //--------------------------------------------------------------------------
  //   Private Methods:
  //--------------------------------------------------------------------------

  //--------------------------------------------------------------------------
  //   Nested Top-Level Classes or Interfaces
  //--------------------------------------------------------------------------
}

