/*
 * 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.geode.management.internal.cli;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.BreakIterator;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.ConsoleHandler;
import java.util.logging.FileHandler;
import java.util.logging.Formatter;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;

import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.cache.Cache;
import org.apache.geode.management.internal.cli.shell.GfshConfig;

/**
 * NOTE: Should be used only in 1. gfsh process 2. on a Manager "if" log is required to be sent back
 * to gfsh too. For logging only on manager use, cache.getLogger()
 *
 * @since GemFire 7.0
 */
public class LogWrapper {
  private static final Object INSTANCE_LOCK = new Object();
  @MakeNotStatic
  private static volatile LogWrapper INSTANCE = null;

  private Logger logger;

  private LogWrapper(Cache cache) {
    logger = Logger.getLogger(getClass().getCanonicalName());

    if (cache != null && !cache.isClosed()) {
      logger.addHandler(cache.getLogger().getHandler());
    }
    logger.setUseParentHandlers(false);
  }

  /**
   * Used in the manager when logging is required to be sent back to gfsh
   */
  public static LogWrapper getInstance(Cache cache) {
    if (INSTANCE == null) {
      synchronized (INSTANCE_LOCK) {
        if (INSTANCE == null) {
          INSTANCE = new LogWrapper(cache);
        }
      }
    }

    return INSTANCE;
  }

  /**
   * used in the gfsh process
   */
  public static LogWrapper getInstance() {
    return getInstance(null);
  }

  public void configure(GfshConfig config) {
    if (config.isLoggingEnabled()) {
      try {
        FileHandler fileHandler = new FileHandler(config.getLogFilePath(),
            config.getLogFileSizeLimit(), config.getLogFileCount(), true);
        fileHandler.setFormatter(new GemFireFormatter());
        fileHandler.setLevel(config.getLogLevel());
        logger.addHandler(fileHandler);
        logger.setLevel(config.getLogLevel());
      } catch (SecurityException | IOException e) {
        addDefaultConsoleHandler(logger, e.getMessage(), config.getLogFilePath());
      }
    }
  }

  private static void addDefaultConsoleHandler(Logger logger, String errorMessage,
      String logFilePath) {
    ConsoleHandler consoleHandler = new ConsoleHandler();
    consoleHandler.setFormatter(new GemFireFormatter());
    logger.addHandler(consoleHandler);

    System.err
        .println("ERROR: Could not log to file: " + logFilePath + ". Reason: " + errorMessage);
    System.err.println("Logs will be written on Console.");
    try {
      Thread.sleep(3000); // sleep for 3 secs for the message to appear
    } catch (InterruptedException ignore) {
    }
  }

  /**
   * Closes the current LogWrapper.
   */
  public static void close() {
    synchronized (INSTANCE_LOCK) {
      if (INSTANCE != null) {
        Logger innerLogger = INSTANCE.logger;
        // remove any existing handlers
        cleanupLogger(innerLogger);
      }
      // make singleton null
      INSTANCE = null;
    }
  }

  /**
   * Removed all the handlers of the given {@link Logger} instance.
   *
   * @param logger {@link Logger} to be cleaned up.
   */
  private static void cleanupLogger(Logger logger) {
    if (logger != null) {
      Handler[] handlers = logger.getHandlers();
      for (Handler handler : handlers) {
        handler.close();
        logger.removeHandler(handler);
      }
    }
  }

  /**
   * Make logger null when the singleton (which was referred by INSTANCE) gets garbage collected.
   * Makes an attempt at removing associated {@link Handler}s of the {@link Logger}.
   */
  @Override
  protected void finalize() throws Throwable {
    cleanupLogger(logger);
    logger = null;
  }

  public void setParentFor(Logger otherLogger) {
    if (otherLogger.getParent() != logger) {
      otherLogger.setParent(logger);
    }
  }

  public void setLogLevel(Level newLevel) {
    if (logger.getLevel() != newLevel) {
      logger.setLevel(newLevel);
    }
  }

  public Level getLogLevel() {
    return logger.getLevel();
  }

  Logger getLogger() {
    return logger;
  }

  public boolean severeEnabled() {
    return logger.isLoggable(Level.SEVERE);
  }

  public void severe(String message) {
    if (severeEnabled()) {
      logger.severe(message);
    }
  }

  public void severe(String message, Throwable t) {
    if (severeEnabled()) {
      logger.log(Level.SEVERE, message, t);
    }
  }

  public boolean warningEnabled() {
    return logger.isLoggable(Level.WARNING);
  }

  public void warning(String message) {
    if (warningEnabled()) {
      logger.warning(message);
    }
  }

  public void warning(String message, Throwable t) {
    if (warningEnabled()) {
      logger.log(Level.WARNING, message, t);
    }
  }

  public boolean infoEnabled() {
    return logger.isLoggable(Level.INFO);
  }

  public void info(String message) {
    if (infoEnabled()) {
      logger.info(message);
    }
  }

  public void info(String message, Throwable t) {
    if (infoEnabled()) {
      logger.log(Level.INFO, message, t);
    }
  }

  public boolean configEnabled() {
    return logger.isLoggable(Level.CONFIG);
  }

  public void config(String message) {
    if (configEnabled()) {
      logger.config(message);
    }
  }

  public void config(String message, Throwable t) {
    if (configEnabled()) {
      logger.log(Level.CONFIG, message, t);
    }
  }

  public boolean fineEnabled() {
    return logger.isLoggable(Level.FINE);
  }

  public void fine(String message) {
    if (fineEnabled()) {
      logger.fine(message);
    }
  }

  public void fine(String message, Throwable t) {
    if (fineEnabled()) {
      logger.log(Level.FINE, message, t);
    }
  }

  public boolean finerEnabled() {
    return logger.isLoggable(Level.FINER);
  }

  public void finer(String message) {
    if (finerEnabled()) {
      logger.finer(message);
    }
  }

  public void finer(String message, Throwable t) {
    if (finerEnabled()) {
      logger.log(Level.FINER, message, t);
    }
  }

  public boolean finestEnabled() {
    return logger.isLoggable(Level.FINEST);
  }

  public void finest(String message) {
    if (finestEnabled()) {
      logger.finest(message);
    }
  }

  public void finest(String message, Throwable t) {
    if (finestEnabled()) {
      logger.log(Level.FINEST, message, t);
    }
  }

  /**
   *
   * @since GemFire 7.0
   */
  static class GemFireFormatter extends Formatter {
    private static final String FORMAT = "yyyy/MM/dd HH:mm:ss.SSS z";

    private final SimpleDateFormat sdf = new SimpleDateFormat(FORMAT);

    @Override
    public synchronized String format(LogRecord record) {
      StringWriter sw = new StringWriter();
      PrintWriter pw = new PrintWriter(sw);

      pw.println();
      pw.print('[');
      pw.print(record.getLevel().getName().toLowerCase());
      pw.print(' ');
      pw.print(formatDate(new Date(record.getMillis())));
      String threadName = Thread.currentThread().getName();
      if (threadName != null) {
        pw.print(' ');
        pw.print(threadName);
      }
      pw.print(" tid=0x");
      pw.print(Long.toHexString(Thread.currentThread().getId()));
      pw.print("] ");
      pw.print("(msgTID=");
      pw.print(record.getThreadID());

      pw.print(" msgSN=");
      pw.print(record.getSequenceNumber());
      pw.print(") ");

      String msg = record.getMessage();
      if (msg != null) {
        try {
          formatText(pw, msg, 40);
        } catch (RuntimeException e) {
          pw.println(msg);
          pw.println("Ignoring the following exception:");
          e.printStackTrace(pw);
        }
      } else {
        pw.println();
      }
      if (record.getThrown() != null) {
        record.getThrown().printStackTrace(pw);
      }
      pw.close();
      try {
        sw.close();
      } catch (IOException ignore) {
      }
      return sw.toString();
    }

    private void formatText(PrintWriter writer, String target, int initialLength) {
      BreakIterator boundary = BreakIterator.getLineInstance();
      boundary.setText(target);
      int start = boundary.first();
      int end = boundary.next();
      int lineLength = initialLength;

      while (end != BreakIterator.DONE) {
        // Look at the end and only accept whitespace breaks
        char endChar = target.charAt(end - 1);
        while (!Character.isWhitespace(endChar)) {
          int lastEnd = end;
          end = boundary.next();
          if (end == BreakIterator.DONE) {
            // give up. We are at the end of the string
            end = lastEnd;
            break;
          }
          endChar = target.charAt(end - 1);
        }
        int wordEnd = end;
        if (endChar == '\n') {
          // trim off the \n since println will do it for us
          wordEnd--;
          if (wordEnd > 0 && target.charAt(wordEnd - 1) == '\r') {
            wordEnd--;
          }
        } else if (endChar == '\t') {
          // figure tabs use 8 characters
          lineLength += 7;
        }
        String word = target.substring(start, wordEnd);
        lineLength += word.length();
        writer.print(word);
        if (endChar == '\n' || endChar == '\r') {
          // force end of line
          writer.println();
          writer.print("  ");
          lineLength = 2;
        }
        start = end;
        end = boundary.next();
      }
      if (lineLength != 0) {
        writer.println();
      }
    }

    private String formatDate(Date date) {
      return sdf.format(date);
    }
  }
}
