package com.tradier.raven.logging;

import static org.slf4j.Logger.ROOT_LOGGER_NAME;
import io.dropwizard.logging.async.AsyncLoggingEventAppenderFactory;
import io.dropwizard.logging.filter.ThresholdLevelFilterFactory;
import io.dropwizard.logging.layout.DropwizardLayoutFactory;

import java.util.Optional;

import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;

/**
 * A class adding a configured {@link com.getsentry.raven.logback.SentryAppender} to the root
 * logger.
 */
public final class RavenBootstrap {
  private RavenBootstrap() { /* No instance methods */ }

  /**
   * Bootstrap the SLF4J root logger with a configured
   * {@link com.getsentry.raven.logback.SentryAppender}.
   *
   * @param dsn The DSN (Data Source Name) for your project
   * @param cleanRootLogger If true, detach and stop all other appenders from the root logger
   */
  public static void bootstrap(final String dsn, boolean cleanRootLogger) {
    bootstrap(dsn, Optional.empty(), cleanRootLogger);
  }

  /**
   * Bootstrap the SLF4J root logger with a configured
   * {@link com.getsentry.raven.logback.SentryAppender}.
   *
   * @param dsn The DSN (Data Source Name) for your project
   * @param tags Custom tags to send to Sentry along with errors
   * @param cleanRootLogger If true, detach and stop all other appenders from the root logger
   */
  public static void bootstrap(final String dsn, Optional<String> tags, boolean cleanRootLogger) {
    final RavenAppenderFactory raven = new RavenAppenderFactory();
    raven.setThreshold(Level.ERROR);
    raven.setDsn(dsn);
    raven.setTags(tags);

    registerAppender(dsn, cleanRootLogger, raven);
  }

  /**
   * Bootstrap the SLF4J root logger with a configured
   * {@link com.getsentry.raven.logback.SentryAppender}.
   *
   * @param dsn The DSN (Data Source Name) for your project
   * @param tags Custom tags to send to Sentry along with errors
   * @param cleanRootLogger If true, detach and stop all other appenders from the root logger
   * @param environment The environment name to pass to Sentry
   * @param release The release name to pass to Sentry
   */
  public static void bootstrap(final String dsn, Optional<String> tags, boolean cleanRootLogger,
      Optional<String> environment, Optional<String> release) {
    final RavenAppenderFactory raven = new RavenAppenderFactory();
    raven.setThreshold(Level.ERROR);
    raven.setDsn(dsn);
    raven.setTags(tags);
    raven.setEnvironment(environment);
    raven.setRelease(release);

    registerAppender(dsn, cleanRootLogger, raven);
  }

  /**
   * Bootstrap the SLF4J root logger with a configured
   * {@link com.getsentry.raven.logback.SentryAppender}.
   *
   * @param dsn The DSN (Data Source Name) for your project
   * @param tags Custom tags to send to Sentry along with errors
   * @param cleanRootLogger If true, detach and stop all other appenders from the root logger
   * @param environment The environment name to pass to Sentry
   * @param release The release name to pass to Sentry
   * @param serverName The server name to pass to Sentry
   */
  public static void bootstrap(final String dsn, Optional<String> tags, boolean cleanRootLogger,
      Optional<String> environment, Optional<String> release, Optional<String> serverName) {
    final RavenAppenderFactory raven = new RavenAppenderFactory();
    raven.setThreshold(Level.ERROR);
    raven.setDsn(dsn);
    raven.setTags(tags);
    raven.setEnvironment(environment);
    raven.setRelease(release);
    raven.setServerName(serverName);

    registerAppender(dsn, cleanRootLogger, raven);
  }

  private static void registerAppender(String dsn, boolean cleanRootLogger,
      RavenAppenderFactory raven) {
    final Logger root = (Logger) LoggerFactory.getLogger(ROOT_LOGGER_NAME);

    if (cleanRootLogger) {
      root.detachAndStopAllAppenders();
    }

    final ThresholdLevelFilterFactory levelFilterFactory = new ThresholdLevelFilterFactory();
    final DropwizardLayoutFactory layoutFactory = new DropwizardLayoutFactory();
    final AsyncLoggingEventAppenderFactory asyncAppenderFactory = new AsyncLoggingEventAppenderFactory();
    root.addAppender(raven.build(root.getLoggerContext(), dsn, layoutFactory, levelFilterFactory,
        asyncAppenderFactory));
  }
}

@@ -614,24 +614,295 @@
 thods */ %7D%0A%0A
+  /**%0A   * Bootstrap the SLF4J root logger with a configured%0A   * %7B@link com.getsentry.raven.logback.SentryAppender%7D.%0A   *%0A   * @param dsn The DSN (Data Source Name) for your project%0A   */%0A  public static void bootstrap(final String dsn) %7B%0A    bootstrap(dsn, true);%0A  %7D%0A%0A
   /**%0A   * B
@@ -1763,181 +1763,63 @@
     
-final RavenAppenderFactory raven = new RavenAppenderFactory();%0A    raven.setThreshold(Level.ERROR);%0A    raven.setDsn(dsn);%0A    raven.setTags(tags);%0A%0A    registerAppender(dsn
+bootstrap(dsn, tags, Optional.empty(), Optional.empty()
 , cl
@@ -1823,39 +1823,32 @@
  cleanRootLogger
-, raven
 );%0A  %7D%0A%0A  /**%0A  
@@ -2091,102 +2091,8 @@
 ors%0A
-   * @param cleanRootLogger If true, detach and stop all other appenders from the root logger%0A
    *
@@ -2197,32 +2197,126 @@
  pass to Sentry%0A
+   * @param cleanRootLogger If true, detach and stop all other appenders from the root logger%0A
    */%0A  public s
@@ -2380,33 +2380,8 @@
 ags,
- boolean cleanRootLogger,
 %0A   
@@ -2441,259 +2441,100 @@
 ease
-) %7B%0A    final RavenAppenderFactory raven = new RavenAppenderFactory();%0A    raven.setThreshold(Level.ERROR);%0A    raven.setDsn(dsn);%0A    raven.setTags(tags);%0A    raven.setEnvironment(environment);%0A    raven.setRelease(release);%0A%0A    registerAppender(dsn
+, boolean cleanRootLogger) %7B%0A    bootstrap(dsn, tags, environment, release, Optional.empty()
 , cl
@@ -2538,39 +2538,32 @@
  cleanRootLogger
-, raven
 );%0A  %7D%0A%0A  /**%0A  
@@ -2806,102 +2806,8 @@
 ors%0A
-   * @param cleanRootLogger If true, detach and stop all other appenders from the root logger%0A
    *
@@ -2973,24 +2973,118 @@
 s to Sentry%0A
+   * @param cleanRootLogger If true, detach and stop all other appenders from the root logger%0A
    */%0A  publ
@@ -3152,33 +3152,8 @@
 ags,
- boolean cleanRootLogger,
 %0A   
@@ -3238,16 +3238,47 @@
 rverName
+,%0A      boolean cleanRootLogger
 ) %7B%0A    
@@ -4088,24 +4088,32 @@
 derFactory =
+%0A       
  new AsyncLo

update RavenBootstrap method signatures