package io.github.hapjava.impl.http.impl;

import io.github.hapjava.impl.http.HomekitClientConnection;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import org.apache.commons.io.HexDump;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class BinaryHandler extends ByteToMessageCodec<ByteBuf> {

  private static final Logger logger = LoggerFactory.getLogger(BinaryHandler.class);

  private final HomekitClientConnection connection;
  private boolean started = false;

  public BinaryHandler(HomekitClientConnection connection) {
    this.connection = connection;
  }

  @Override
  protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception {
    if (started) {
      byte[] b = new byte[msg.readableBytes()];
      msg.readBytes(b);
      traceData("Sending data", b, ctx);
      out.writeBytes(connection.encryptResponse(b));
    } else {
      out.writeBytes(msg);
    }
  }

  @Override
  protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
    byte[] b = new byte[in.readableBytes()];
    in.readBytes(b);
    byte[] decrypted = connection.decryptRequest(b);
    traceData("Received data", decrypted, ctx);
    out.add(Unpooled.copiedBuffer(decrypted));
    started = true;
  }

  @Override
  public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    boolean errorLevel = !(cause instanceof IOException);
    if (errorLevel) {
      logger.error("Exception in binary handler", cause);
    } else {
      logger.debug("Exception in binary handler", cause);
    }
    super.exceptionCaught(ctx, cause);
  }

  private void traceData(String msg, byte[] b, ChannelHandlerContext ctx) throws Exception {
    if (logger.isTraceEnabled() && b.length > 0) {
      try (ByteArrayOutputStream stream = new ByteArrayOutputStream()) {
        HexDump.dump(b, 0, stream, 0);
        stream.flush();
        logger.trace(
            String.format(
                "%s [%s]:%n%s%n",
                msg,
                ctx.channel().remoteAddress().toString(),
                stream.toString(StandardCharsets.UTF_8.name())));
      }
    }
  }
}

@@ -262,46 +262,8 @@
 ec;%0A
-import java.io.ByteArrayOutputStream;%0A
 impo
@@ -282,24 +282,24 @@
 OException;%0A
+
 import java.
@@ -355,46 +355,8 @@
 st;%0A
-import org.apache.commons.io.HexDump;%0A
 impo
@@ -872,24 +872,67 @@
 (started) %7B%0A
+      debugData(%22Sending data%22, msg, ctx);%0A
       byte%5B%5D
@@ -995,49 +995,8 @@
 b);%0A
-      traceData(%22Sending data%22, b, ctx);%0A
     
@@ -1330,21 +1330,76 @@
 b);%0A    
-trace
+ByteBuf outBuf = Unpooled.copiedBuffer(decrypted);%0A    debug
 Data(%22Re
@@ -1412,25 +1412,22 @@
  data%22, 
-decrypted
+outBuf
 , ctx);%0A
@@ -1442,40 +1442,14 @@
 add(
-Unpooled.copiedBuffer(decrypted)
+outBuf
 );%0A 
@@ -1851,21 +1851,21 @@
 te void 
-trace
+debug
 Data(Str
@@ -1873,22 +1873,23 @@
 ng msg, 
-byte%5B%5D
+ByteBuf
  b, Chan
@@ -1951,13 +1951,13 @@
 r.is
-Trace
+Debug
 Enab
@@ -1965,166 +1965,12 @@
 ed()
- && b.length %3E 0) %7B%0A      try (ByteArrayOutputStream stream = new ByteArrayOutputStream()) %7B%0A        HexDump.dump(b, 0, stream, 0);%0A        stream.flush();%0A  
+) %7B%0A
     
@@ -1982,13 +1982,13 @@
 ger.
-trace
+debug
 (%0A  
@@ -1995,18 +1995,16 @@
         
-  
 String.f
@@ -2024,18 +2024,16 @@
         
-  
 %22%25s %5B%25s%5D
@@ -2041,15 +2041,11 @@
 %25n%25s
-%25n
 %22,%0A
-  
     
@@ -2058,32 +2058,16 @@
     msg,
-%0A               
  ctx.cha
@@ -2104,31 +2104,10 @@
 g(),
-%0A                stream
+ b
 .toS
@@ -2138,27 +2138,12 @@
 TF_8
-.name())));%0A      %7D
+)));
 %0A   

improve logging