package net.bavrd.faces;

import java.util.Collections;

import org.vertx.java.core.Handler;
import org.vertx.java.core.MultiMap;
import org.vertx.java.core.buffer.Buffer;
import org.vertx.java.core.eventbus.Message;
import org.vertx.java.core.http.HttpClient;
import org.vertx.java.core.http.HttpClientResponse;
import org.vertx.java.core.http.HttpServerRequest;
import org.vertx.java.core.json.JsonObject;

import com.google.common.escape.Escaper;
import com.google.common.net.UrlEscapers;

import net.bavrd.core.EventEnum;
import net.bavrd.core.Face;
import net.bavrd.core.FaceMessage;
import net.bavrd.utils.VertxHandlers;

public class SlackFace extends Face {

  private int port;
  private String route;
  private String botName;
  private String token;

  @Override
  public void startBavrd() {
    port = container.config().getInteger("port", 8080);
    route = container.config().getString("route", "/incoming/slack/");
    botName = container.config().getString("botName", "bavrd");
    token = container.config().getString("api_token", "");

    vertx.createHttpServer()
        .requestHandler(new Handler<HttpServerRequest>() {
          @Override
          public void handle(final HttpServerRequest req) {
            if (!req.path().equalsIgnoreCase(route)
                || !req.method().equals("POST")) {
              req.response().setStatusCode(404).end();
            } else {
              req.expectMultiPart(true);
              req.bodyHandler(new Handler<Buffer>() {
                @Override
                public void handle(Buffer buffer) {
                  String payload = buffer.toString();
                  container.logger().debug(payload);

                  MultiMap attributes = req.formAttributes();
                  String trigger = attributes.get("trigger_word");
                  String message = attributes.get("text");
                  message = message.replaceFirst(trigger, "").trim();
                  String userId = attributes.get("user_id");
                  String userName = attributes.get("user_name");
                  String channelName = attributes.get("channel_name");
                  String channelId = attributes.get("channel_id");

                  //TODO verifications
                  FaceMessage incoming = FaceMessage.incoming(userId, userName, channelId, channelName, message);

                  vertx.eventBus().publish(EventEnum.INCOMING.vertxEndpoint, incoming.asJson());
                  req.response().end();
                }
              });
            }
          }
        })
        .listen(port);

    final HttpClient slack = vertx.createHttpClient()
        .setSSL(true)
        .setTrustAll(true)
        .setPort(443)
        .setHost("slack.com");

    vertx.eventBus().registerHandler(EventEnum.OUTGOING.vertxEndpoint, new Handler<Message<JsonObject>>() {
      @Override
      public void handle(Message<JsonObject> m) {
        Escaper esc = UrlEscapers.urlFormParameterEscaper();
        FaceMessage body = FaceMessage.decodeFrom(m.body());

        //sanitize the text and convert to Slack formatting
        String formattedText = formatText(body.message.trim());

        StringBuffer payload = new StringBuffer()
            .append("token=")
            .append(esc.escape(token))
            .append("&text=")
            .append(esc.escape(formattedText))
            .append("&username=")
            .append(esc.escape(botName));

        if (body.isReply && body.isPrivate)
          payload.append("&channel=").append(esc.escape("@"+body.userId));
        else
          payload.append("&channel=").append(esc.escape(body.channelId));

        Handler<HttpClientResponse> responseHandler;
        if (container.logger().isDebugEnabled())
          responseHandler = new Handler<HttpClientResponse>() {
            @Override
            public void handle(HttpClientResponse response) {
              container.logger().debug(response.statusCode() + " : " + response.statusMessage());
            }
          };
        else
          responseHandler = VertxHandlers.noOpHandler();

        slack.post("/api/chat.postMessage", responseHandler)
            .putHeader("Content-Type", "application/x-www-form-urlencoded")
            .end(payload.toString());
      }
    });
  }

  @Override
  protected String formatBold(String text) {
    return "*"+text+"*";
  }

  @Override
  protected String formatItalic(String text) {
    return "_"+text+"_";
  }

  @Override
  protected String formatCode(String text) {
    return "`"+text+"`";
  }

  @Override
  protected String formatImg(String imageSrc, String imageAlt) {
    //no image support in Slack, try to give a link to image with alt text as label if possible
    if (imageAlt.length() > 0)
      return "<"+imageSrc+"|"+imageAlt+">";
    return imageSrc;
  }

  @Override
  protected String formatNewLine() {
    return "\n";
  }

  @Override
  public java.util.Map<String, String> getHelp() {
    return Collections.emptyMap();
  }
}

@@ -753,16 +753,39 @@
 g token;
+%0A  private String icon;
 %0A%0A  @Ove
@@ -1068,16 +1068,75 @@
 n%22, %22%22);
+%0A    icon = container.config().getString(%22bot_icon%22, null);
 %0A%0A    ve
@@ -3516,24 +3516,244 @@
 botName));%0A%0A
+        if (icon != null) %7B%0A          if (icon.startsWith(%22:%22))%0A            payload.append(%22&icon_emoji=%22);%0A          else%0A            payload.append(%22&icon_url=%22);%0A          payload.append(esc.escape(icon));%0A        %7D%0A%0A
         if (

allow to set an icon or emoji in SlackFace config (bot_icon)