package com.github.kyleburton.logback;

import ch.qos.logback.core.AppenderBase;
import ch.qos.logback.core.LogbackException;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.IThrowableProxy;
import ch.qos.logback.classic.spi.StackTraceElementProxy;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.concurrent.atomic.AtomicLong;
import java.util.List;

import com.aphyr.riemann.client.EventDSL;
import com.aphyr.riemann.client.RiemannClient;
import com.aphyr.riemann.client.SynchronousTransport;;
import com.aphyr.riemann.client.UdpTransport;
import com.aphyr.riemann.Proto.Event;
import com.aphyr.riemann.Proto.Msg;

public class RiemannAppender<E> extends AppenderBase<E> {
  private static final String DEFAULT_PORT = "5555";
  private static final String DEFAULT_HOST = "localhost";

  private String serviceName     = "*no-service-name*";
  private String riemannHostname = DEFAULT_HOST;
  private String riemannPort     = DEFAULT_PORT;
  private String hostname        = "*no-host-name*";
  private int    maxBufferSize   = 16384;

  public static AtomicLong timesCalled = new AtomicLong(0);

  private static boolean debug = false;
  // private static boolean debug = true;

  private RiemannClient riemannClient = null;

  public void start() {
    try {
      if (debug) {
        System.err.println(String.format("%s.start()", this));
      }
      SynchronousTransport transport = new SimpleUdpTransport(riemannHostname, Integer.parseInt(riemannPort));
      final RiemannClient cli = new RiemannClient(transport);
      riemannClient = cli;
      if (debug) {
        System.err.println(String.format("%s.start: connecting", this));
      }
      riemannClient.connect();
      if (debug) {
        System.err.println(String.format("%s.start: connected", this));
      }
    }
    catch (IOException ex) {
      if (debug) {
        System.err.println(String.format("%s: Error initializing: %s", this, ex));
      }
      throw new RuntimeException(ex);
    }
    super.start();
  }

  public void stop() {
    if (debug) {
      System.err.println(String.format("%s.stop()", this));
    }
    if (riemannClient != null) {
      try {
        riemannClient.disconnect();
      }
      catch (IOException ex) {
        // do nothing, it's ok
      }
    }
    super.stop();
  }

  public String toString () {
    return String.format(
        "RiemannAppender{hashCode=%s;serviceName=%s;riemannHostname=%s;riemannPort=%s;hostname=%s}",
        hashCode(),
        serviceName,
        riemannHostname,
        riemannPort,
        hostname);
  }

  private String getStackTraceFromEvent( ILoggingEvent logEvent ) {
    IThrowableProxy throwable = logEvent.getThrowableProxy();
    if ( null != throwable && null != throwable.getStackTraceElementProxyArray() ) {
      StringBuilder sb = new StringBuilder();
      for ( StackTraceElementProxy elt : throwable.getStackTraceElementProxyArray() ) {
        sb.append(elt.toString());
        sb.append("\n");
      }
      return sb.toString();
    }

    if (logEvent.getCallerData() != null) {
      if (debug) {
        System.err.println(String.format("%s.append: falling back to appender stacktrace: ", this));
      }
      StringBuilder sb = new StringBuilder();
      for ( StackTraceElement elt : logEvent.getCallerData()) {
        sb.append(elt);
        sb.append("\n");
      }
      return sb.toString();
    }

    return null;
  }

  protected synchronized void append(E event) /* throws LogbackException */ {
    timesCalled.incrementAndGet();
    ILoggingEvent logEvent = (ILoggingEvent) event;
    EventDSL rEvent;
    try {
      rEvent = riemannClient.event().
        service(serviceName).
        host(hostname).
        state("error").
        attribute("message", logEvent.getFormattedMessage());

      String stInfo = getStackTraceFromEvent(logEvent);
      if (null != stInfo) {
        rEvent.attribute("stacktrace", stInfo);
      }

      try {
        if (debug) {
          System.err.println(String.format("%s.append: sending riemann event: %s", this, rEvent));
        }
        rEvent.send();
        if (debug) {
          System.err.println(String.format("%s.append(logEvent): sent to riemann %s:%s", this, riemannHostname, riemannPort));
        }
      }
      catch (Exception ex) {
        if (debug) {
          System.err.println(String.format(
                "%s: Error sending event %s",
                this,
                ex));
          ex.printStackTrace();
        }

        riemannClient.reconnect();
        if (null != rEvent) {
          rEvent.send();
        }
      }
    }
    catch (Exception ex) {
      // do nothing
      if (debug) {
        System.err.println(String.format("RiemannAppender.append: Error during append(): %s", ex));
        ex.printStackTrace();
      }
    }

    //System.err.println(String.format(
    //      "RiemannAppender{serviceName=%s;riemannHostname=%s;riemannPort=%s;hostname=%s}",
    //      serviceName,
    //      riemannHostname,
    //      riemannPort,
    //      hostname));

    //System.err.println("RiemannAppender: event: " + event);
    //System.err.println("RiemannAppender: event.getClass(): " + event.getClass());
  }


  public void setServiceName (String s) {
    serviceName = s;
  }

  public void setRiemannHostname (String s) {
    riemannHostname = s;
  }

  public void setRiemannPort (String s) {
    riemannPort = s;
  }

  public void setHostname (String s) {
    hostname = s;
  }

  public void setDebug (String s) {
    debug = "true" == s;
  }
}

@@ -37,95 +37,8 @@
 k;%0A%0A
-import ch.qos.logback.core.AppenderBase;%0Aimport ch.qos.logback.core.LogbackException;%0A%0A
 impo
@@ -195,174 +195,48 @@
 xy;%0A
-%0A
 import 
-java.io.IOException;%0Aimport java.net.InetAddress;%0Aimport java.net.UnknownHostException;%0Aimport java.util.concurrent.atomic.AtomicLong;%0Aimport java.util.List;%0A
+ch.qos.logback.core.AppenderBase;
 %0Aimp
@@ -374,25 +374,25 @@
 ansport;
-;
+%0A
 %0Aimport 
 com.aphy
@@ -387,118 +387,73 @@
 ort 
-com.aphyr.riemann.client.UdpTransport;%0Aimport com.aphyr.riemann.Proto.Event;%0Aimport com.aphyr.riemann.Proto.Ms
+java.io.IOException;%0Aimport java.util.concurrent.atomic.AtomicLon
 g;%0A%0A
@@ -832,50 +832,8 @@
 e*%22;
-%0A  private int    maxBufferSize   = 16384;
 %0A%0A  
@@ -934,50 +934,8 @@
 lse;
-%0A  // private static boolean debug = true;
 %0A%0A  
@@ -1224,15 +1224,9 @@
     
-final R
+r
 iema
@@ -1238,12 +1238,8 @@
 ent 
-cli 
 = ne
@@ -1270,35 +1270,8 @@
 t);%0A
-      riemannClient = cli;%0A
     
@@ -5239,13 +5239,18 @@
 rue%22
- == s
+.equals(s)
 ;%0A  

Fix compiler warnings.