package net.northking.cctp.element.internal.protocol.socket.def01;

import com.alibaba.fastjson.JSON;
import net.northking.cctp.element.internal.dto.FieldDto;
import net.northking.cctp.element.internal.protocol.socket.MessageHandler;
import net.northking.cctp.element.internal.protocol.socket.SocketResponseData;
import net.northking.cctp.element.internal.utils.BinaryUtils;
import net.northking.cctp.element.util.Assert;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

public class Def01MessageHandler implements MessageHandler {

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

    private static final String NAME = "Socket变长协议";

    //请求头
    private String header;
    /**
     * 字符集
     */
    private Charset charset;

    public Def01MessageHandler(String header,String charsetName) {
        try {
            this.charset = Charset.forName(charsetName);
        } catch (Exception e) {
            logger.error("设置字符集" + charsetName + "失败", e);
            this.charset = StandardCharsets.UTF_8;
        }
        this.header = header;
    }

    @Override
    public String getProtocolName() {
        return NAME;
    }

    @Override
    public byte[] getRequestMessage(String requestText) throws Exception {
        Assert.notNull(requestText, "请求报文空");
        StringBuilder str = new StringBuilder("");
        if(StringUtils.isNotBlank(this.header)){
            //拼接请求头
            List<FieldDto> fieldDtos = JSON.parseArray(this.header, FieldDto.class);
            BinaryUtils.setHeaderLength(fieldDtos,str);
        }
        String head = str.toString();
        byte[] bytes = requestText.getBytes(charset);
        int length = bytes.length;
        int total = length;
        byte[] headBytes = null;
        if(StringUtils.isNotBlank(head)){
            headBytes = head.getBytes(charset);
            int leng = headBytes.length;
            total += leng;
        }
        ByteBuffer buffer = ByteBuffer.allocate(total);
        if(headBytes!=null){
            buffer.put(headBytes);
        }
        buffer.put(bytes);

        return buffer.array();
    }

    @Override
    public FutureTask<SocketResponseData> getResponseFuture(InputStream in) throws Exception {
        FutureTask task = new FutureTask(() -> new SocketResponseData().body(readResponseMessage(in)));
        return task;
    }

    /**
     * 读取响应报文
     */
    private String readResponseMessage(InputStream in) throws Exception {

        List<byte[]> list = new ArrayList<>();
        int total = 0;
        byte[] part1 = new byte[1024];
        int len = in.read(part1);
        list.add(ArrayUtils.subarray(part1, 0, len));
        total += len;
        int num = 1;
        while (true) {
            TimeUnit.MILLISECONDS.sleep(500);
            int l = in.available();
            if (l <= 0) {
                num++;
            } else {
                num = 0;
                byte[] part = new byte[l];
                int read = in.read(part);
                list.add(part);
                total += l;
            }
            if (num > 2) {
                break;
            }
        }
        ByteBuffer buffer = ByteBuffer.allocate(total);
        list.forEach(part -> buffer.put(part));
        return new String(buffer.array(), charset);
    }


    @Override
    public String toString() {
        return ToStringBuilder.reflectionToString(this);
    }

}
