package io.netstrap.core.netty.datagram;

import io.netstrap.core.http.Keepalive;
import io.netstrap.core.http.datagram.HttpResponse;
import io.netstrap.core.http.header.HeaderPublicKey;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;

import java.util.Map;
import java.util.Objects;

import static io.netstrap.core.http.header.HeaderPublicKey.CONTENT_LENGTH;

/**
 * Netty HTTP响应体
 *
 * @author minghu.zhang
 * @date 2018/11/08
 */
public class NettyHttpResponse extends HttpResponse {

    /**
     * channel数据管道
     */
    private Channel channel;
    /**
     * 响应对象
     */
    private FullHttpResponse response;

    /**
     * 构造函数
     */
    public NettyHttpResponse(Channel channel) {
        super();
        this.channel = channel;
    }

    @Override
    public void write() {
        if (isWritable()) {
            createResponse();
            addHeaders();
            writeFlush();
        }
    }

    /**
     * 创建响应对象
     */
    private void createResponse() {
        HttpResponseStatus status = HttpResponseStatus.valueOf(getStatus());
        if (Objects.nonNull(getBody())) {
            ByteBuf buffer = Unpooled.wrappedBuffer(getBody().getBytes());
            response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status, buffer);
        } else {
            response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, status);
        }
    }

    /**
     * 添加头信息
     */
    private void addHeaders() {
        for (String key : getHeader().keySet()) {
            response.headers().add(key, getHeader().get(key));
        }
    }

    /**
     * 写数据
     */
    private void writeFlush() {
        //添加数据长度响应头
        int length = Objects.isNull(getBody()) ? 0 : getBody().getBytes().length;
        response.headers().add(CONTENT_LENGTH, length);
        ChannelFuture future = channel.writeAndFlush(response);

        if (!isKeepAlive()) {
            future.addListener(ChannelFutureListener.CLOSE);
        }
        //只能写一次。
        setWritable(false);
    }

    /**
     * 设置keep-alive
     */
    public HttpResponse keepAlive(HttpVersion httpVersion, Map<String, String> header) {

        String connection = header.getOrDefault(HeaderPublicKey.CONNECTION, Keepalive.CLOSE_ALIVE).toLowerCase();

        //设置keep-alive
        if ((httpVersion.equals(HttpVersion.HTTP_1_1) && !connection.equals(Keepalive.CLOSE_ALIVE))) {
            setKeepAlive(true);
        } else if (httpVersion.equals(HttpVersion.HTTP_1_0) && connection.equals(Keepalive.KEEP_ALIVE)) {
            setKeepAlive(true);
        }

        if (isKeepAlive()) {
            addHeader(HeaderPublicKey.CONNECTION, Keepalive.KEEP_ALIVE);
        }

        return this;
    }

}