package cn.com.ty.lift.business.common.http;

import cn.com.ty.lift.business.framework.BusinessBasicException;
import cn.hutool.core.date.DateUtil;
import com.ning.http.client.*;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileInputStream;
import java.util.*;

/**
 * @Author xp-zhao@logictech.cn
 * @CreateOn 2016/06/29^ 13:32
 */
@Slf4j
public class BasicHttpClient extends HttpBasic {

    public static final Map<String, Object> formHeaders = new HashMap<String, Object>() {{
        put("Content-Type", "application/x-www-form-urlencoded");
    }};

    public static final Map<String, Object> jsonHeaders = new HashMap<String, Object>() {{
        put("Content-Type", "application/json");
    }};

    public static Response sends(final String method, final String url, final Map<String, Object> params, final Map<String, Object> headers) throws RuntimeException {
        try (AsyncHttpClient c = new AsyncHttpClient()) {
            AsyncHttpClient.BoundRequestBuilder accept;
            if (Objects.equals(method.toUpperCase(), GET)) {
                accept = c.prepareGet(url);
                accept.addQueryParams(new ArrayList<Param>() {{
                    if (null != params)
                        for (Map.Entry<String, Object> _entry : params.entrySet())
                            add(new Param(_entry.getKey(), Objects.toString(_entry.getValue())));
                }});
            } else {
                accept = c.preparePost(url);
                if (null != params)
                    if (headers != null && !Objects.equals(headers.get("Content-Type"), "application/json"))
                        accept.setBody(("time=" + DateUtil.now() + buildParameters(params)));
                    else {
                        accept.setBody(gson.toJson(params));
                    }
            }
            //set headers
            if (null != headers) {
                for (Map.Entry<String, Object> _entry : headers.entrySet())
                    accept.setHeader(_entry.getKey(), Objects.toString(_entry.getValue()));
            }
            //set charset utf-8
            accept.setBodyEncoding("UTF-8");

            return accept.execute(new AsyncCompletionHandler<Response>() {
                @Override
                public Response onCompleted(Response response) throws Exception {
                    return response;
                }

                @Override
                public STATE onBodyPartReceived(HttpResponseBodyPart content) throws Exception {
                    return super.onBodyPartReceived(content);
                }

                @Override
                public STATE onStatusReceived(HttpResponseStatus status) throws Exception {
                    return super.onStatusReceived(status);
                }

                @Override
                public STATE onHeadersReceived(HttpResponseHeaders headers) throws Exception {
                    return super.onHeadersReceived(headers);
                }

                @Override
                public void onThrowable(Throwable t) {
                    super.onThrowable(t);
                }

                /**
                 * Invoked when the content (a {@link File}, {@link String} or {@link FileInputStream} has been fully
                 * written on the I/O socket.
                 *
                 * @return a {@link STATE} telling to CONTINUE or ABORT the current processing.
                 */
                @Override
                public STATE onHeaderWriteCompleted() {
                    return super.onHeaderWriteCompleted();
                }

                /**
                 * Invoked when the content (a {@link File}, {@link String} or {@link FileInputStream} has been fully
                 * written on the I/O socket.
                 *
                 * @return a {@link STATE} telling to CONTINUE or ABORT the current processing.
                 */
                @Override
                public STATE onContentWriteCompleted() {
                    return super.onContentWriteCompleted();
                }

                /**
                 * Invoked when the I/O operation associated with the {@link Request} body as been progressed.
                 *
                 * @param amount  The amount of bytes to transfer.
                 * @param current The amount of bytes transferred
                 * @param total   The total number of bytes transferred
                 * @return a {@link STATE} telling to CONTINUE or ABORT the current processing.
                 */
                @Override
                public STATE onContentWriteProgress(long amount, long current, long total) {
                    return super.onContentWriteProgress(amount, current, total);
                }
            }).get();
        } catch (Exception e) {
            log.error("httpClient执行请求出现错误，错误描述" + e, e);
            throw new BusinessBasicException(e);
        }
    }
}
