// Copyright (C) 2013 The Android Open Source Project
//
// 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 com.googlesource.gerrit.plugins.its.base.testutil.log;

import com.google.common.collect.ImmutableMap;
import com.google.common.flogger.FluentLogger;
import java.util.Collection;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ThrowableInformation;

/** Utility functions for dealing with various Loggers */
public class LogUtil {
  private static final ImmutableMap<org.apache.log4j.Level, Level> log4jToJul =
      new ImmutableMap.Builder<org.apache.log4j.Level, Level>()
          .put(org.apache.log4j.Level.OFF, Level.OFF)
          .put(org.apache.log4j.Level.FATAL, Level.SEVERE)
          .put(org.apache.log4j.Level.ERROR, Level.SEVERE)
          .put(org.apache.log4j.Level.WARN, Level.WARNING)
          .put(org.apache.log4j.Level.INFO, Level.INFO)
          .put(org.apache.log4j.Level.DEBUG, Level.FINE)
          .put(org.apache.log4j.Level.TRACE, Level.FINEST)
          .put(org.apache.log4j.Level.ALL, Level.FINEST)
          .build();

  /**
   * Makes sure that Loggers for a given name add their events to a collection
   *
   * <p>This is useful for capturing logged events during testing and being able to run assertions
   * on them.
   *
   * <p>We will never be able to cover all possible backends of the Logging flavour of the day. For
   * now we cover Log4j and JUL. If you use a different default logging backend, please send in
   * patches.
   *
   * @param logName The name of the loggers to make log to the given collection.
   * @param collection The collection to add log events to.
   * @param level The level the logger should be set to.
   */
  public static CollectionAppender logToCollection(
      String logName, Collection<LogRecord> collection, org.apache.log4j.Level level) {

    CollectionAppender appender = new CollectionAppender(collection);

    logToCollectionLog4j(logName, appender, level);
    logToCollectionJul(logName, appender, log4jToJul.get(level));

    return appender;
  }

  /**
   * Make a Log4j logger log to a given appender at a certain level
   *
   * @param logName The logger that should log to the appender.
   * @param appender The appender to log to.
   * @param level The level to user for the logger.
   */
  private static void logToCollectionLog4j(
      String logName, CollectionAppender appender, org.apache.log4j.Level level) {
    Logger log = LogManager.getLogger(logName);
    log.setLevel(level);
    log.removeAllAppenders();
    log.addAppender(appender);
  }

  /**
   * Make a java.util.logging logger log to a given appender at a certain level
   *
   * @param logName The logger that should log to the appender.
   * @param appender The appender to log to.
   * @param level The level to user for the logger.
   */
  private static void logToCollectionJul(String logName, CollectionAppender appender, Level level) {
    // We'd love to simply get the logger of name `logName` and directly
    // configure that. While this works for running the tests in bazel, it
    // fails when running tests from within Eclipse. In Eclipse getting the
    // logger of the same name here and from the class-under-test will get two
    // different loggers, due to backend calling from a different class. So we
    // instead resort to configuring the root logger and filtering the logName
    // in the appender.

    // The description above works for the 2nd, 3rd, ... test of a test case in
    // Eclipse, but not for the first. To cover the first test as well, we
    // beforehand tell Flogger to set things up by getting any random logger
    // /before/ we configure the root logger.
    @SuppressWarnings("unused")
    FluentLogger unused = FluentLogger.forEnclosingClass();

    java.util.logging.Logger julLogger = java.util.logging.Logger.getLogger("");
    julLogger.setLevel(level);

    julLogger.addHandler(
        new Handler() {
          @Override
          public void publish(LogRecord record) {
            if (record.getLoggerName().equals(logName)) {
              appender.append(record);
            }
          }

          @Override
          public void flush() {}

          @Override
          public void close() throws SecurityException {}
        });
  }

  /**
   * Converts a Log4j Logging Event to a JUL LogRecord
   *
   * <p>This is not a full conversion, but covers only the fields we care about. That is the logged
   * message and eventual thrown Throwables.
   *
   * @param event The Log4j LoggingEvent to convert
   * @return The corresponding JUL LogRecord
   */
  public static LogRecord logRecordFromLog4jLoggingEvent(LoggingEvent event) {
    LogRecord logRecord = new LogRecord(Level.ALL, event.getRenderedMessage());
    ThrowableInformation tInfo = event.getThrowableInformation();
    if (tInfo != null) {
      logRecord.setThrown(tInfo.getThrowable());
    }
    return logRecord;
  }

  /**
   * Check if a JUL and a Log4j Level correspond
   *
   * @param left The JUL Level to check.
   * @param right The Log4j Level to check.
   * @return True, if and only if the levels correspond.
   */
  public static boolean equalLevels(Level left, org.apache.log4j.Level right) {
    Level julRight = log4jToJul.get(right);
    return (left == null && right == null) || (left != null && left.equals(julRight));
  }
}
