package cn.reghao.autodop.common.docker.unixdomain;

import cn.reghao.autodop.common.util.ExceptionUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.*;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * @author reghao
 * @date 2020-01-15 10:13:21
 */
public class HttpClient {
    private UnixSocketClient unixSocketClient;

    public HttpClient(UnixSocketClient unixSocketClient) {
        this.unixSocketClient = unixSocketClient;
    }

    private FullHttpResponse errMsg(Exception e) {
        FullHttpResponse httpResponse =
                new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR);
        ByteBuf errMsg = Unpooled.buffer(10);
        errMsg.writeBytes(ExceptionUtil.errorMsg(e).getBytes(StandardCharsets.UTF_8));
        httpResponse.replace(errMsg);
        return httpResponse;
    }

    public FullHttpResponse get(String uri, List<DockerHeader> headers) throws IOException, InterruptedException {
        FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uri);
        request.headers().set(HttpHeaderNames.HOST, "netty");
        request.headers().set(HttpHeaderNames.ACCEPT, "Accept: */*");
        if (headers != null) {
            headers.forEach(header -> {
                request.headers().set(header.getName(), header.getValue());
            });
        }

        return unixSocketClient.syncSend(request);
    }

    public FullHttpResponse post(String uri, List<DockerHeader> headers) throws IOException, InterruptedException {
        FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, uri);
        request.headers().set(HttpHeaderNames.HOST, "netty");
        request.headers().set(HttpHeaderNames.ACCEPT, "Accept: */*");
        if (headers != null) {
            headers.forEach(header -> {
                request.headers().set(header.getName(), header.getValue());
            });
        }

        return unixSocketClient.syncSend(request);
    }

    public FullHttpResponse postJson(String uri, List<DockerHeader> headers, String json) throws IOException, InterruptedException {
        ByteBuf byteBuf = Unpooled.copiedBuffer(json, StandardCharsets.UTF_8);

        FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, uri);
        request.headers().set(HttpHeaderNames.HOST, "netty");
        request.headers().set(HttpHeaderNames.ACCEPT, "Accept: */*");
        request.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json");
        request.headers().set(HttpHeaderNames.CONTENT_LENGTH, byteBuf.readableBytes());
        if (headers != null) {
            headers.forEach(header -> {
                request.headers().set(header.getName(), header.getValue());
            });
        }
        request.content().clear().writeBytes(byteBuf);
        return unixSocketClient.syncSend(request);
    }

    public FullHttpResponse postFile(String uri, List<DockerHeader> headers, File file) throws IOException, InterruptedException {
        byte[] bytes = transfer(file);
        long len = bytes.length;
        ByteBuf content = Unpooled.wrappedBuffer(bytes);

        FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, uri, content);
        request.headers().set(HttpHeaderNames.HOST, "netty");
        request.headers().set(HttpHeaderNames.ACCEPT, "Accept: */*");
        request.headers().set(HttpHeaderNames.CONTENT_LENGTH, String.valueOf(len));
        if (headers != null) {
            headers.forEach(header -> {
                request.headers().set(header.getName(), header.getValue());
            });
        }

        return unixSocketClient.syncSend(request);
    }

    private byte[] transfer(File file) throws IOException {
        BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) != -1) {
            bos.write(buf, 0, len);
        }

        bos.close();
        return bos.toByteArray();
    }

    public FullHttpResponse delete(String uri, List<DockerHeader> headers) throws IOException, InterruptedException {
        FullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.DELETE, uri);
        request.headers().set(HttpHeaderNames.HOST, "netty");
        request.headers().set(HttpHeaderNames.ACCEPT, "Accept: */*");
        if (headers != null) {
            headers.forEach(header -> {
                request.headers().set(header.getName(), header.getValue());
            });
        }

        return unixSocketClient.syncSend(request);
    }

    public void close() {
        unixSocketClient.close();
    }
}
