/*
 * 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.internal.logging.log4j;

import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.logging.log4j.core.Appender;
import org.apache.logging.log4j.core.Core;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.Layout;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.appender.AbstractOutputStreamAppender;
import org.apache.logging.log4j.core.appender.ConsoleAppender;
import org.apache.logging.log4j.core.appender.ConsoleAppender.Target;
import org.apache.logging.log4j.core.appender.ManagerFactory;
import org.apache.logging.log4j.core.appender.OutputStreamManager;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginBuilderAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginBuilderFactory;
import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
import org.apache.logging.log4j.core.util.NullOutputStream;

import org.apache.geode.annotations.Immutable;
import org.apache.geode.annotations.VisibleForTesting;
import org.apache.geode.annotations.internal.MakeNotStatic;

/**
 * Wraps {@link ConsoleAppender} with additions defined in {@link PausableAppender} and
 * {@link DebuggableAppender}.
 */
@Plugin(name = GeodeConsoleAppender.PLUGIN_NAME, category = Core.CATEGORY_NAME,
    elementType = Appender.ELEMENT_TYPE, printObject = true)
@SuppressWarnings("unused")
public class GeodeConsoleAppender extends AbstractOutputStreamAppender<OutputStreamManager>
    implements PausableAppender, DebuggableAppender {

  public static final String PLUGIN_NAME = "GeodeConsole";

  private static final boolean START_PAUSED_BY_DEFAULT = false;
  @Immutable
  private static final Target DEFAULT_TARGET = Target.SYSTEM_OUT;
  @MakeNotStatic
  private static final AtomicInteger COUNT = new AtomicInteger();
  @Immutable
  private static final GeodeConsoleManagerFactory MANAGER_FACTORY =
      new GeodeConsoleManagerFactory();

  private final ConsoleAppender delegate;
  private final boolean debug;
  private final List<LogEvent> events;

  private volatile boolean paused;

  protected GeodeConsoleAppender(final String name,
      final Layout<? extends Serializable> layout,
      final Filter filter,
      final OutputStreamManager manager,
      final ConsoleAppender delegate) {
    this(name, layout, filter, manager, true, START_PAUSED_BY_DEFAULT, false, delegate);
  }

  protected GeodeConsoleAppender(final String name,
      final Layout<? extends Serializable> layout,
      final Filter filter,
      final OutputStreamManager manager,
      final boolean ignoreExceptions,
      final boolean startPaused,
      final boolean debug,
      final ConsoleAppender delegate) {
    super(name, layout, filter, ignoreExceptions, true, manager);
    this.delegate = delegate;
    this.debug = debug;
    if (debug) {
      events = Collections.synchronizedList(new ArrayList<>());
    } else {
      events = Collections.emptyList();
    }
    paused = startPaused;
  }

  public static GeodeConsoleAppender createDefaultAppenderForLayout(
      final Layout<? extends Serializable> layout) {
    // this method cannot use the builder class without introducing an infinite loop due to
    // DefaultConfiguration
    return new GeodeConsoleAppender(PLUGIN_NAME + "-" + COUNT.incrementAndGet(), layout, null,
        getDefaultManager(DEFAULT_TARGET, false, false, layout), true, false, false,
        ConsoleAppender.createDefaultAppenderForLayout(layout));
  }

  @PluginBuilderFactory
  public static <B extends Builder<B>> B newBuilder() {
    return new Builder<B>().asBuilder();
  }

  /**
   * Builds GeodeConsoleAppender instances.
   *
   * @param <B> The type to build
   */
  public static class Builder<B extends Builder<B>> extends AbstractOutputStreamAppender.Builder<B>
      implements org.apache.logging.log4j.core.util.Builder<GeodeConsoleAppender> {

    @PluginBuilderAttribute
    @Required
    private Target target = DEFAULT_TARGET;

    @PluginBuilderAttribute
    private boolean follow;

    @PluginBuilderAttribute
    private boolean direct;

    @PluginBuilderAttribute
    private boolean startPaused = START_PAUSED_BY_DEFAULT;

    @PluginBuilderAttribute
    private boolean debug;

    public B setTarget(final Target aTarget) {
      target = aTarget;
      return asBuilder();
    }

    public B setFollow(final boolean shouldFollow) {
      follow = shouldFollow;
      return asBuilder();
    }

    public B setDirect(final boolean shouldDirect) {
      direct = shouldDirect;
      return asBuilder();
    }

    public B setStartPaused(final boolean shouldStartPaused) {
      startPaused = shouldStartPaused;
      return asBuilder();
    }

    public boolean isStartPaused() {
      return debug;
    }

    public B setDebug(final boolean shouldDebug) {
      debug = shouldDebug;
      return asBuilder();
    }

    public boolean isDebug() {
      return debug;
    }

    @Override
    public GeodeConsoleAppender build() {
      ConsoleAppender.Builder delegate = new ConsoleAppender.Builder();
      // AbstractAppender
      delegate.withFilter(getFilter());
      delegate.withName(getName() + "_DELEGATE");
      delegate.withIgnoreExceptions(isIgnoreExceptions());
      delegate.withLayout(getLayout());
      // AbstractOutputStreamAppender
      delegate.withImmediateFlush(isImmediateFlush());
      delegate.withBufferedIo(isBufferedIo());
      delegate.withBufferSize(getBufferSize());
      // ConsoleAppender
      delegate.setTarget(target);
      delegate.setFollow(follow);
      delegate.setDirect(direct);

      Layout<? extends Serializable> layout = getOrCreateLayout(target.getDefaultCharset());
      return new GeodeConsoleAppender(getName(), layout,
          getFilter(), getManager(target, follow, direct, layout),
          isIgnoreExceptions(), startPaused, debug, delegate.build());
    }
  }

  @Override
  public void append(final LogEvent event) {
    if (isPaused()) {
      return;
    }
    delegate.append(event);
    if (debug) {
      events.add(event);
    }
  }

  @Override
  public void start() {
    LOGGER.info("Starting {}.", this);
    delegate.start();
    super.start();
  }

  @Override
  public void stop() {
    LOGGER.info("Stopping {}.", this);
    delegate.stop();
    super.stop();
  }

  @Override
  public void pause() {
    LOGGER.debug("Pausing {}.", this);
    paused = true;
  }

  @Override
  public void resume() {
    LOGGER.debug("Resuming {}.", this);
    paused = false;
  }

  @Override
  public boolean isPaused() {
    return paused;
  }

  @Override
  public void clearLogEvents() {
    events.clear();
  }

  @Override
  public List<LogEvent> getLogEvents() {
    return events;
  }

  @Override
  public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode()) + ":" + getName()
        + " {paused=" + paused + ", debug=" + debug + ", delegate=" + delegate + "}";
  }

  @VisibleForTesting
  ConsoleAppender getDelegate() {
    return delegate;
  }

  private static OutputStreamManager getDefaultManager(final Target target, final boolean follow,
      final boolean direct, final Layout<? extends Serializable> layout) {

    OutputStream os = NullOutputStream.getInstance();
    String managerName = target.name() + '.' + follow + '.' + direct + "-" + COUNT.get();
    return OutputStreamManager.getManager(managerName, new FactoryData(os, managerName, layout),
        MANAGER_FACTORY);
  }

  private static OutputStreamManager getManager(final Target target, final boolean follow,
      final boolean direct, final Layout<? extends Serializable> layout) {
    OutputStream os = NullOutputStream.getInstance();
    String managerName = "null." + target.name() + '.' + follow + '.' + direct;
    return OutputStreamManager.getManager(managerName, new FactoryData(os, managerName, layout),
        MANAGER_FACTORY);
  }

  private static class FactoryData {
    private final OutputStream os;
    private final String name;
    private final Layout<? extends Serializable> layout;

    public FactoryData(final OutputStream os, final String type,
        final Layout<? extends Serializable> layout) {
      this.os = os;
      name = type;
      this.layout = layout;
    }
  }

  private static class AccessibleOutputStreamManager extends OutputStreamManager {

    protected AccessibleOutputStreamManager(final OutputStream os, final String streamName,
        final Layout<?> layout, final boolean writeHeader) {
      super(os, streamName, layout, writeHeader);
    }

    protected AccessibleOutputStreamManager(final OutputStream os, final String streamName,
        final Layout<?> layout,
        final boolean writeHeader, final int bufferSize) {
      super(os, streamName, layout, writeHeader, bufferSize);
    }
  }

  private static class GeodeConsoleManagerFactory implements
      ManagerFactory<OutputStreamManager, FactoryData> {

    @Override
    public OutputStreamManager createManager(final String name, final FactoryData data) {
      return new AccessibleOutputStreamManager(data.os, data.name, data.layout, true);
    }
  }
}
