package com.tradier.raven.logging;

import static com.google.common.base.Preconditions.checkNotNull;
import io.dropwizard.logging.AbstractAppenderFactory;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.Layout;
import ch.qos.logback.core.filter.Filter;
import ch.qos.logback.core.spi.FilterReply;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeName;
import com.getsentry.raven.logback.SentryAppender;

@JsonTypeName("raven")
public class RavenAppenderFactory extends AbstractAppenderFactory {

  private final static String APPENDER_NAME = "dropwizard-raven";

  @JsonProperty
  private String dsn = null;

  @JsonProperty
  private String tags = null;

  @JsonProperty
  private String release = null;

  @JsonProperty
  private String environment = null;

  public String getDsn() {
    return dsn;
  }

  public void setDsn(String dsn) {
    this.dsn = dsn;
  }

  public String getTags() {
    return tags;
  }

  public void setTags(String tags) {
    this.tags = tags;
  }

  public void setRelease(String release) {
    this.release = release;
  }

  public void setEnvironment(String environment) {
    this.environment = environment;
  }

  @Override
  public Appender<ILoggingEvent> build(LoggerContext context, String applicationName,
      Layout<ILoggingEvent> layout) {
    checkNotNull(context);

    final SentryAppender appender = new SentryAppender();
    appender.setName(APPENDER_NAME);
    appender.setContext(context);
    appender.setDsn(dsn);
    if (release != null) {
      appender.setRelease(release);
    }
    if (environment != null) {
      appender.setEnvironment(environment);
    }
    if (tags != null) {
      appender.setTags(tags);
    }
    appender.start();

    final Appender<ILoggingEvent> asyncAppender = wrapAsync(appender);
    addThresholdFilter(asyncAppender, threshold);
    addDroppingRavenLoggingFilter(asyncAppender);

    return asyncAppender;
  }

  public void addDroppingRavenLoggingFilter(Appender<ILoggingEvent> appender) {
    final Filter<ILoggingEvent> filter = new DroppingRavenLoggingFilter();
    filter.start();
    appender.addFilter(filter);
  }

  public static class DroppingRavenLoggingFilter extends Filter<ILoggingEvent> {
    @Override
    public FilterReply decide(ILoggingEvent event) {
      if (event.getLoggerName().startsWith("com.getsentry.raven")) {
        return FilterReply.DENY;
      } else {
        return FilterReply.ACCEPT;
      }
    }
  }
}

@@ -799,20 +799,27 @@
  String 
-tags
+environment
  = null;
@@ -899,35 +899,81 @@
 vate String 
-environment
+serverName = null;%0A%0A  @JsonProperty%0A  private String tags
  = null;%0A%0A  
@@ -1097,20 +1097,27 @@
 ring get
-Tags
+Environment
 () %7B%0A   
@@ -1124,20 +1124,27 @@
  return 
-tags
+environment
 ;%0A  %7D%0A%0A 
@@ -1163,216 +1163,472 @@
  set
-Tags(String tags) %7B%0A    this.tags = tags;%0A  %7D%0A%0A  public void setRelease(String release) %7B%0A    this.release = release;%0A  %7D%0A%0A  public void setEnvironment(String environment) %7B%0A    this.environment = environment
+Environment(String environment) %7B%0A    this.environment = environment;%0A  %7D%0A%0A  public String getRelease() %7B%0A    return release;%0A  %7D%0A%0A  public void setRelease(String release) %7B%0A    this.release = release;%0A  %7D%0A%0A  public String getServerName() %7B%0A    return serverName;%0A  %7D%0A%0A  public void setServerName(String serverName) %7B%0A    this.serverName = serverName;%0A  %7D%0A%0A  public String getTags() %7B%0A    return tags;%0A  %7D%0A%0A  public void setTags(String tags) %7B%0A    this.tags = tags
 ;%0A  
@@ -1949,16 +1949,97 @@
 n(dsn);%0A
+    if (environment != null) %7B%0A      appender.setEnvironment(environment);%0A    %7D%0A
     if (
@@ -2103,35 +2103,34 @@
   %7D%0A    if (
-environment
+serverName
  != null) %7B%0A
@@ -2147,39 +2147,37 @@
 nder.set
-Environment(environment
+ServerName(serverName
 );%0A    %7D

add serverName support to appender