package net.northking.cctp.element.internal.protocol.http;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import net.northking.cctp.element.core.exception.ExecuteException;
import net.northking.cctp.element.internal.protocol.ResponseData;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.StatusLine;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.message.BufferedHeader;
import org.apache.http.util.CharArrayBuffer;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * HttpResponseData
 *
 * @author fengxiang.zhang
 * @date 2022/4/13
 * @since 1.0
 */
public class HttpResponseData implements ResponseData {

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

    private Header[] headers;
    private int statusCode;
    private String responseBody;
    private Long responseTime;
    private String chartset = StandardCharsets.UTF_8.name();

    public HttpResponseData response(CloseableHttpResponse response) throws Exception {
        if (response != null) {
            StatusLine statusLine = response.getStatusLine();
            statusCode = statusLine.getStatusCode();
            headers = response.getAllHeaders();
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                responseBody = EntityUtils.toString(entity);
            }
        }
        return this;
    }

    @Override
    public String getResponseHeaders() {
        StringBuffer headerBuf = new StringBuffer();
        if (headers != null) {
            for (int i = 0; i < headers.length; ++i) {
                Header responseHeader = headers[i];
                this.writeHeader(headerBuf, responseHeader);
            }
        }
        return headerBuf.toString();
    }

    @Override
    public String getResponseBody() {
        return responseBody;
    }

    @Override
    public Object toJson() {
        JSONObject response = new JSONObject(true);
        response.put("statusCode", this.statusCode);
        Map<String,String> headMap = new HashMap<>();
        Map<String,Object> resultMap = new HashMap<>();
        Object body = responseBody;
        try {
        for (int i = 0; i < headers.length; ++i) {
            Header h = headers[i];
            String decode = URLDecoder.decode(h.getValue(), chartset);
            headMap.put(h.getName(), decode);
        }
            if (headMap.containsKey("Content-Type") && headMap.get("Content-Type").contains("application/json")) {
                body = JSON.parse(body.toString());
            }
        } catch (Exception e) {
            logger.error("响应信息转化失败", e);
            throw new ExecuteException("响应信息转化失败", e);
        }
        resultMap.put("headers",headMap);
        resultMap.put("body",body);
        response.put("responseTime", responseTime);
        response.put("context", resultMap);
        return response;
    }

    @Override
    public Long getResponseTime() {
        return responseTime;
    }

    public int getStatusCode() {
        return statusCode;
    }

    public HttpResponseData time(Long responseTime) {
        this.responseTime = responseTime;
        return this;
    }

    public HttpResponseData urlDecode(String charset) {
        if (null != charset && charset.length() > 0) {
            this.chartset = charset;
        }
        return this;
    }

    private void writeHeader(StringBuffer headerBuffer, Header header) {
        if (header instanceof BufferedHeader) {
            CharArrayBuffer buffer = ((BufferedHeader) header).getBuffer();
            headerBuffer.append(buffer.buffer(), 0, buffer.length()).append('\n');
        } else {
            headerBuffer.append(header.getName()).append(": ").append(header.getValue()).append('\n');
        }
    }

}
