package net.northking.cctp.element.mobile.utils;

import net.northking.cctp.element.core.exception.ExecuteException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RequestCallback;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestTemplate;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URI;
import java.util.Arrays;

public class HttpUtils<T> {

    private static final RestTemplate restTemplate;

    private static final RestTemplate downLoadRestTemplate;

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

    static {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(15000);
        factory.setReadTimeout(60000);
        restTemplate = new RestTemplate(factory);

        SimpleClientHttpRequestFactory downloadFactory = new SimpleClientHttpRequestFactory();
        downloadFactory.setConnectTimeout(15000);
        downloadFactory.setReadTimeout(10*60*1000);
        downLoadRestTemplate = new RestTemplate(downloadFactory);
    }

    public static <T> T doPost(URI uri, HttpEntity<?> httpEntity,Class<T> responseType){
        ResponseEntity<T> response = null;
        try {
            response = restTemplate.exchange(uri, HttpMethod.POST, httpEntity, responseType);
        } catch (Exception e) {
            logger.error("请求出错,地址：{}，原因：{}",uri.getPath(),e);
            throw new ExecuteException(String.format("http请求【%s】出错", uri.getPath()));
        }
        return response.getBody();
    }

    public static <T> T doPost(String uri, HttpEntity<?> httpEntity,Class<T> responseType){
        ResponseEntity<T> response = null;
        try {
            response = restTemplate.exchange(uri, HttpMethod.POST, httpEntity, responseType);
        } catch (Exception e) {
            logger.error("请求出错,地址：{}，原因：{}",uri,e);
            throw new ExecuteException(String.format("http请求【%s】出错", uri));
        }
        return response.getBody();
    }
    public static <T> T doPost(String uri, HttpEntity<?> httpEntity,Class<T> responseType, int timeout){
        ResponseEntity<T> response = null;
        try {
            RestTemplate template = createRestTemplate(timeout);
            response = template.exchange(uri, HttpMethod.POST, httpEntity, responseType);
        } catch (Exception e) {
            logger.error("请求出错,地址：{}，原因：{}",uri,e);
            throw new ExecuteException(String.format("http请求【%s】出错", uri));
        }
        return response.getBody();
    }

    private static RestTemplate createRestTemplate(int timeout) {
        SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(5000);
        factory.setReadTimeout(timeout);
        return new RestTemplate(factory);
    }

    public static <T> T doGet(URI uri, Class<T> responseType){
        ResponseEntity<T> response = null;
        try {
            response = restTemplate.exchange(uri, HttpMethod.GET, null, responseType);
        } catch (Exception e) {
            logger.error("请求出错,地址：{}，原因：{}",uri.getPath(),e);
            throw new ExecuteException(String.format("http请求【%s】出错", uri.getPath()));
        }
        return response.getBody();
    }

    public static void downloadFileToLocal(String sourceUrl,String targetDir,String fileName){
        final String[] installAddr = {""};
        RequestCallback callback = request -> request.getHeaders().setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));
        ResponseExtractor responseExtractor = clientHttpResponse -> {
            File path = new File(targetDir);
            if (!path.exists()) {
                path.mkdirs();
            }
            File file = new File(targetDir + "/" + fileName);
            InputStream inputStream = clientHttpResponse.getBody();
            FileOutputStream outputStream = new FileOutputStream(file);
            byte[] data = new byte[1024 * 1024];
            int length = 0;
            while ((length = inputStream.read(data, 0, data.length)) > 0) {
                outputStream.write(data, 0, length);
            }
            installAddr[0] = file.getAbsolutePath();
            return file;
        };
        downLoadRestTemplate.execute(sourceUrl, HttpMethod.GET, callback, responseExtractor);
    }
}
