/*
 * Copyright 2007 Google Inc.
 * 
 * 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.google.gwt.dev.util.log;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;

import java.util.HashSet;

/**
 * Abstract base class for TreeLoggers.
 */
public abstract class AbstractTreeLogger extends TreeLogger {

  private static class UncommittedBranchData {

    public final Throwable caught;
    public final String message;
    public final TreeLogger.Type type;
    private final HelpInfo helpInfo;

    public UncommittedBranchData(Type type, String message, Throwable caught,
        HelpInfo helpInfo) {
      this.caught = caught;
      this.message = message;
      this.type = type;
      this.helpInfo = helpInfo;
    }
  }

  // This message is package-protected so that the unit test can access it.
  static final String OUT_OF_MEMORY_MSG = "Out of memory; to increase the "
      + "amount of memory, use the -Xmx flag at startup (java -Xmx128M ...)";

  // This message is package-protected so that the unit test can access it.
  static final String STACK_OVERFLOW_MSG = "Stack overflow; to increase the "
      + "stack size, use the -Xss flag at startup (java -Xss1M ...)";

  public static String getStackTraceAsString(Throwable e) {
    // Show the exception info for anything other than "UnableToComplete".
    if (e == null || e instanceof UnableToCompleteException) {
      return null;
    }
    // For each cause, print the requested number of entries of its stack
    // trace, being careful to avoid getting stuck in an infinite loop.
    //
    StringBuffer message = new StringBuffer();
    Throwable currentCause = e;
    String causedBy = "";
    HashSet<Throwable> seenCauses = new HashSet<Throwable>();
    while (currentCause != null && !seenCauses.contains(currentCause)) {
      seenCauses.add(currentCause);

      message.append(causedBy);
      causedBy = "\nCaused by: "; // after 1st, all say "caused by"
      message.append(currentCause.getClass().getName());
      message.append(": " + currentCause.getMessage());
      StackTraceElement[] stackElems = currentCause.getStackTrace();
      if (stackElems != null) {
        for (int i = 0; i < stackElems.length; ++i) {
          message.append("\n\tat ");
          message.append(stackElems[i].toString());
        }
      }

      currentCause = currentCause.getCause();
    }
    return message.toString();
  }

  protected static String getExceptionName(Throwable e) {
    if (e == null || e instanceof UnableToCompleteException) {
      return null;
    }
    return e.getClass().getSimpleName();
  }

  protected TreeLogger.Type logLevel = TreeLogger.ALL;

  protected AbstractTreeLogger parent;

  private int indexWithinMyParent;

  private int nextChildIndex;

  private final Object nextChildIndexLock = new Object();

  private UncommittedBranchData uncommitted;

  /**
   * The constructor used when creating a top-level logger.
   */
  protected AbstractTreeLogger() {
  }

  /**
   * Implements branching behavior that supports lazy logging for low-priority
   * branched loggers.
   */
  @Override
  public final synchronized TreeLogger branch(TreeLogger.Type type, String msg,
      Throwable caught, HelpInfo helpInfo) {

    if (msg == null) {
      msg = "(Null branch message)";
    }

    // Compute at which index the new child will be placed.
    //
    int childIndex = allocateNextChildIndex();

    // The derived class creates the child logger.
    AbstractTreeLogger childLogger = doBranch();

    // Set up the child logger.
    //
    // Unsynchronized operations on childLogger are safe since no other
    // thread could have a reference to it yet.
    childLogger.logLevel = logLevel;

    // Take a snapshot of the index that the branched child should have.
    //
    childLogger.indexWithinMyParent = childIndex;

    // Have the child hang onto this (its parent logger).
    //
    childLogger.parent = this;

    // We can avoid committing this branch entry until and unless some
    // child (or grandchild) tries to log something that is loggable,
    // in which case there will be cascading commits of the parent branches.
    //
    childLogger.uncommitted = new UncommittedBranchData(type, msg, caught,
        helpInfo);

    // This logic is intertwined with log(). If a log message is associated
    // with a special error condition, then we turn it into a branch,
    // so this method can be called directly from log(). It is of course
    // also possible for someone to call branch() directly. In either case, we
    // (1) turn the original message into an ERROR and
    // (2) drop an extra log message that explains how to recover
    String specialErrorMessage = causedBySpecialError(caught);
    if (specialErrorMessage != null) {
      type = TreeLogger.ERROR;
      childLogger.log(type, specialErrorMessage, null);
    }

    // Decide whether we want to log the branch message eagerly or lazily.
    //
    if (isLoggable(type)) {
      // We can commit this branch entry eagerly since it is a-priori loggable.
      // Commit the parent logger if necessary before continuing.
      //
      childLogger.commitMyBranchEntryInMyParentLogger();
    }

    return childLogger;
  }

  public final int getBranchedIndex() {
    return indexWithinMyParent;
  }

  public final synchronized TreeLogger.Type getMaxDetail() {
    return logLevel;
  }

  public final AbstractTreeLogger getParentLogger() {
    return parent;
  }

  @Override
  public final synchronized boolean isLoggable(TreeLogger.Type type) {
    return !type.isLowerPriorityThan(logLevel);
  }

  /**
   * Immediately logs or ignores the specified messages, based on the specified
   * message type and this logger's settings. If the message is loggable, then
   * parent branches may be lazily created before the log can take place.
   */
  @Override
  public final synchronized void log(TreeLogger.Type type, String msg,
      Throwable caught, HelpInfo helpInfo) {

    if (msg == null) {
      msg = "(Null log message)";
    }

    // If this log message is caused by out of memory or stack overflow, we
    // provide a little extra help by creating a child log message.
    if (causedBySpecialError(caught) != null) {
      branch(TreeLogger.ERROR, msg, caught);
      return;
    }

    int childIndex = allocateNextChildIndex();
    if (isLoggable(type)) {
      commitMyBranchEntryInMyParentLogger();
      doLog(childIndex, type, msg, caught, helpInfo);
    }
  }

  /**
   * @param type the log type representing the most detailed level of logging
   *          that the caller is interested in, or <code>null</code> to choose
   *          the default level.
   */
  public final synchronized void setMaxDetail(TreeLogger.Type type) {
    if (type == null) {
      type = TreeLogger.INFO;
    }
    logLevel = type;
  }

  @Override
  public String toString() {
    return getLoggerId();
  }

  protected int allocateNextChildIndex() {
    synchronized (nextChildIndexLock) {
      // postincrement because we want indices to start at 0
      return nextChildIndex++;
    }
  }

  /**
   * Commits the branch after ensuring that the parent logger (if there is one)
   * has been committed first.
   */
  protected synchronized void commitMyBranchEntryInMyParentLogger() {
    // (Only the root logger doesn't have a parent.)
    //
    if (parent != null) {
      if (uncommitted != null) {
        // Commit the parent first.
        //
        parent.commitMyBranchEntryInMyParentLogger();

        // Let the subclass do its thing to commit this branch.
        //
        parent.doCommitBranch(this, uncommitted.type, uncommitted.message,
            uncommitted.caught, uncommitted.helpInfo);

        // Release the uncommitted state.
        //
        uncommitted = null;
      }
    }
  }

  /**
   * Derived classes should override this method to return a branched logger.
   */
  protected abstract AbstractTreeLogger doBranch();

  /**
   * @deprecated This method has been deprecated; override
   *             {@link #doCommitBranch(AbstractTreeLogger, com.google.gwt.core.ext.TreeLogger.Type, String, Throwable, com.google.gwt.core.ext.TreeLogger.HelpInfo)}
   *             instead.
   * 
   * @param childBeingCommitted
   * @param type
   * @param msg
   * @param caught
   */
  @Deprecated
  protected final void doCommitBranch(AbstractTreeLogger childBeingCommitted,
      TreeLogger.Type type, String msg, Throwable caught) {
  }

  /**
   * Derived classes should override this method to actually commit the
   * specified message associated with this the root of this branch.
   */
  protected abstract void doCommitBranch(
      AbstractTreeLogger childBeingCommitted, TreeLogger.Type type, String msg,
      Throwable caught, HelpInfo helpInfo);

  /**
   * @deprecated This method has been deprecated; override
   *             {@link #branch(com.google.gwt.core.ext.TreeLogger.Type, String, Throwable, com.google.gwt.core.ext.TreeLogger.HelpInfo)
   *             instead.
   * 
   * @param indexOfLogEntryWithinParentLogger
   * @param type
   * @param msg
   * @param caught
   */
  @Deprecated
  protected final void doLog(int indexOfLogEntryWithinParentLogger,
      TreeLogger.Type type, String msg, Throwable caught) {
  }

  /**
   * Derived classes should override this method to actually write a log
   * message. Note that {@link #isLoggable(TreeLogger.Type)} will have already
   * been called.
   */
  protected abstract void doLog(int indexOfLogEntryWithinParentLogger,
      TreeLogger.Type type, String msg, Throwable caught, HelpInfo helpInfo);

  /**
   * Scans <code>t</code> and its causes for {@link OutOfMemoryError} or
   * {@link StackOverflowError}.
   * 
   * @param t a possibly null {@link Throwable}
   * @return true if {@link OutOfMemoryError} or {@link StackOverflowError}
   *         appears anywhere in the cause list or if <code>t</code> is an
   *         {@link OutOfMemoryError} or {@link StackOverflowError.
   */
  private String causedBySpecialError(Throwable t) {
    while (t != null) {
      if (t instanceof OutOfMemoryError) {
        return OUT_OF_MEMORY_MSG;
      } else if (t instanceof StackOverflowError) {
        return STACK_OVERFLOW_MSG;
      }
      t = t.getCause();
    }
    return null;
  }

  private String getLoggerId() {
    if (parent != null) {
      if (parent.parent == null) {
        // Top-level
        return parent.getLoggerId() + getBranchedIndex();
      } else {
        // Nested
        return parent.getLoggerId() + "." + getBranchedIndex();
      }
    } else {
      // The root
      return "#";
    }
  }
}
