package org.mp.api.core.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cftech.core.util.*;
import com.cftech.cos.alioss.AliOssStorageService;
import com.cftech.cos.config.cosconfig.model.Cosconfig;
import com.cftech.cos.core.CosService;
import com.cftech.cos.qcloud.QcloudStorageService;
import com.cftech.cos.qiniu.QiniuStorageService;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.request.UploadFileRequest;
import com.qcloud.cos.sign.Credentials;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.map.HashedMap;
import org.apache.log4j.Logger;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;

@Slf4j
public class HttpRequestProxy {

    // 本地图片目录
    public static final String USER_IMAGES_DIR = SystemConfig.p.getProperty("userfiles.imgdir");

    /**
     * 连接超时
     */
    private static int connectTimeOut = 5000;

    /**
     * 读取数据超时
     */
    private static int readTimeOut = 10000;

    /**
     * 请求编码
     */
    public static String requestEncoding = "UTF-8";

    private static Logger logger = Logger.getLogger(HttpRequestProxy.class);

    /**
     * <pre>
     * 发送带参数的GET的HTTP请求
     * </pre>
     *
     * @param reqUrl     HTTP请求URL
     * @param parameters 参数映射表
     * @return HTTP响应的字符串
     */
    public static String doGet(String reqUrl, Map parameters,
                               String recvEncoding) {
        HttpURLConnection url_con = null;
        String responseContent = null;
        try {
            url_con = doHttpGetConnection(reqUrl, parameters);

            InputStream in = url_con.getInputStream();
            BufferedReader rd = new BufferedReader(new InputStreamReader(in,
                    recvEncoding));
            String tempLine = rd.readLine();
            StringBuffer temp = new StringBuffer();
            String crlf = System.getProperty("line.separator");
            while (tempLine != null) {
                temp.append(tempLine);
                temp.append(crlf);
                tempLine = rd.readLine();
            }
            responseContent = temp.toString();
            rd.close();
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("网络故障", e);
        } finally {
            if (url_con != null) {
                url_con.disconnect();
            }
        }

        return responseContent;
    }

    private static HttpURLConnection doHttpGetConnection(String reqUrl,
                                                         Map parameters) throws IOException {
        HttpURLConnection url_con = null;
        String params = getMapParamsToStr(parameters,
                HttpRequestProxy.requestEncoding);

        URL url = new URL(reqUrl);
        url_con = (HttpURLConnection) url.openConnection();
        url_con.setRequestMethod("GET");
        System.setProperty("sun.net.client.defaultConnectTimeout",
                String.valueOf(HttpRequestProxy.connectTimeOut));// （单位：毫秒）jdk1.4换成这个,连接超时
        System.setProperty("sun.net.client.defaultReadTimeout",
                String.valueOf(HttpRequestProxy.readTimeOut)); // （单位：毫秒）jdk1.4换成这个,读操作超时

        url_con.setDoOutput(true);
        byte[] b = params.toString().getBytes();
        url_con.getOutputStream().write(b, 0, b.length);
        url_con.getOutputStream().flush();
        url_con.getOutputStream().close();

        return url_con;
    }

    /**
     * <pre>
     * 发送不带参数的GET的HTTP请求
     * </pre>
     *
     * @param reqUrl HTTP请求URL
     * @return HTTP响应的字符串
     */
    public static String doGet(String reqUrl, String recvEncoding) {
        HttpURLConnection url_con = null;
        String responseContent = null;
        try {
            StringBuffer params = new StringBuffer();
            String queryUrl = reqUrl;
            int paramIndex = reqUrl.indexOf("?");

            if (paramIndex > 0) {
                queryUrl = reqUrl.substring(0, paramIndex);
                String parameters = reqUrl.substring(paramIndex + 1,
                        reqUrl.length());
                String[] paramArray = parameters.split("&");
                for (int i = 0; i < paramArray.length; i++) {
                    String string = paramArray[i];
                    int index = string.indexOf("=");
                    if (index > 0) {
                        String parameter = string.substring(0, index);
                        String value = string.substring(index + 1,
                                string.length());
                        params.append(parameter);
                        params.append("=");
                        params.append(URLEncoder.encode(value,
                                HttpRequestProxy.requestEncoding));
                        params.append("&");
                    }
                }

                params = params.deleteCharAt(params.length() - 1);
            }

            URL url = new URL(queryUrl);
            url_con = (HttpURLConnection) url.openConnection();
            url_con.setRequestMethod("GET");
            System.setProperty("sun.net.client.defaultConnectTimeout",
                    String.valueOf(HttpRequestProxy.connectTimeOut));// （单位：毫秒）jdk1.4换成这个,连接超时
            System.setProperty("sun.net.client.defaultReadTimeout",
                    String.valueOf(HttpRequestProxy.readTimeOut)); // （单位：毫秒）jdk1.4换成这个,读操作超时

            url_con.setDoOutput(true);
            byte[] b = params.toString().getBytes();
            url_con.getOutputStream().write(b, 0, b.length);
            url_con.getOutputStream().flush();
            url_con.getOutputStream().close();
            InputStream in = url_con.getInputStream();
            BufferedReader rd = new BufferedReader(new InputStreamReader(in,
                    recvEncoding));
            String tempLine = rd.readLine();
            StringBuffer temp = new StringBuffer();
            String crlf = System.getProperty("line.separator");
            while (tempLine != null) {
                temp.append(tempLine);
                temp.append(crlf);
                tempLine = rd.readLine();
            }
            responseContent = temp.toString();
            rd.close();
            in.close();
        } catch (IOException e) {
            logger.error("网络故障", e);
            e.printStackTrace();
        } finally {
            if (url_con != null) {
                url_con.disconnect();
            }
        }

        return responseContent;
    }

    /**
     * <pre>
     * 发送带参数的POST的HTTP请求
     * </pre>
     *
     * @param reqUrl     HTTP请求URL
     * @param parameters 参数映射表
     * @return HTTP响应的字符串
     */
    public static String doPost(String reqUrl, Map parameters,
                                String recvEncoding) {
        HttpURLConnection url_con = null;
        String responseContent = null;
        try {
            String params = getMapParamsToStr(parameters,
                    HttpRequestProxy.requestEncoding);
            URL url = new URL(reqUrl);
            url_con = (HttpURLConnection) url.openConnection();
            url_con.setRequestMethod("POST");
            System.setProperty("sun.net.client.defaultConnectTimeout",
                    String.valueOf(HttpRequestProxy.connectTimeOut));// （单位：毫秒）jdk1.4换成这个,连接超时
            System.setProperty("sun.net.client.defaultReadTimeout",
                    String.valueOf(HttpRequestProxy.readTimeOut)); // （单位：毫秒）jdk1.4换成这个,读操作超时

            url_con.setDoOutput(true);
            byte[] b = params.toString().getBytes();
            url_con.getOutputStream().write(b, 0, b.length);
            url_con.getOutputStream().flush();
            url_con.getOutputStream().close();

            InputStream in = url_con.getInputStream();
            BufferedReader rd = new BufferedReader(new InputStreamReader(in,
                    recvEncoding));
            String tempLine = rd.readLine();
            StringBuffer tempStr = new StringBuffer();
            String crlf = System.getProperty("line.separator");
            while (tempLine != null) {
                tempStr.append(tempLine);
                tempStr.append(crlf);
                tempLine = rd.readLine();
            }
            responseContent = tempStr.toString();
            rd.close();
            in.close();
        } catch (IOException e) {
            logger.error("网络故障", e);
        } finally {
            if (url_con != null) {
                url_con.disconnect();
            }
        }
        return responseContent;
    }

    /**
     * <pre>
     * 发送带参数的POST的HTTP请求
     * </pre>
     *
     * @param reqUrl     HTTP请求URL
     * @param parameters 参数映射表
     * @return HTTP响应的字符串
     */
    public static String doJsonPost(String reqUrl, Map parameters,
                                    String jsonData) {
        HttpURLConnection url_con = null;
        String responseContent = null;
        try {
            String params = getMapParamsToStr(parameters,
                    HttpRequestProxy.requestEncoding);
            String shortUrl = reqUrl + "&" + params;
//			if(reqUrl.contains("/qrcode/create")){//二维码生成利用端链接生成
//				try {
//					String sUrl=JwAccountAPI.getShortUrl(params.replace("access_token=",""),reqUrl + "&" + params);
//					shortUrl=sUrl;
//				} catch (WexinReqException e) {
//					// TODO Auto-generated catch block
//					e.printStackTrace();
//				}
//			}
            URL url = new URL(shortUrl);
            url_con = (HttpURLConnection) url.openConnection();
            url_con.setRequestMethod("POST");
            System.setProperty("sun.net.client.defaultConnectTimeout",
                    String.valueOf(HttpRequestProxy.connectTimeOut));// （单位：毫秒）jdk1.4换成这个,连接超时
            System.setProperty("sun.net.client.defaultReadTimeout",
                    String.valueOf(HttpRequestProxy.readTimeOut)); // （单位：毫秒）jdk1.4换成这个,读操作超时
            url_con.setDoOutput(true);
            url_con.setRequestProperty("Accept", "application/json"); // 设置接收数据的格式
            url_con.setRequestProperty("Content-Type", "application/json"); // 设置发送数据的格式

            byte[] b = jsonData.toString().getBytes("utf-8");
            url_con.getOutputStream().write(b, 0, b.length);
            url_con.getOutputStream().flush();
            url_con.getOutputStream().close();

            InputStream in = url_con.getInputStream();
            BufferedReader rd = new BufferedReader(new InputStreamReader(in,
                    HttpRequestProxy.requestEncoding));
            String tempLine = rd.readLine();
            StringBuffer tempStr = new StringBuffer();
            String crlf = System.getProperty("line.separator");
            while (tempLine != null) {
                tempStr.append(tempLine);
                tempStr.append(crlf);
                tempLine = rd.readLine();
            }
            responseContent = tempStr.toString();
            rd.close();
            in.close();
        } catch (IOException e) {
            logger.error("网络故障", e);
        } finally {
            if (url_con != null) {
                url_con.disconnect();
            }
        }
        return responseContent;
    }

    /**
     * @param reqUrl
     * @param parameters
     * @param recvEncoding
     * @param fileIn       文件流
     * @return
     */
    public static String uploadMedia(String reqUrl, Map parameters,
                                     String recvEncoding, InputStream fileIn, String fileName,
                                     String contentType) {
        HttpURLConnection url_con = null;
        String responseContent = null;
        try {
            // 设置边界
            String BOUNDARY = "----------" + System.currentTimeMillis();
            String params = getMapParamsToStr(parameters,
                    HttpRequestProxy.requestEncoding);

            URL urlObj = new URL(reqUrl + "&" + params.toString());
            // 连接
            url_con = (HttpURLConnection) urlObj.openConnection();
            /**
             * 设置关键值
             */
            url_con.setRequestMethod("POST"); // 以Post方式提交表单，默认get方式
            url_con.setDoInput(true);
            url_con.setDoOutput(true);
            url_con.setUseCaches(false); // post方式不能使用缓存

            // 设置请求头信息
            url_con.setRequestProperty("Connection", "Keep-Alive");
            url_con.setRequestProperty("Charset", recvEncoding);

            // 设置边界
            url_con.setRequestProperty("Content-Type",
                    "multipart/form-data; boundary=" + BOUNDARY);

            // 请求正文信息

            // 第一部分：
            StringBuilder sb = new StringBuilder();
            sb.append("--"); // 必须多两道线
            sb.append(BOUNDARY);
            sb.append("\r\n");
            sb.append("Content-Disposition: form-data;name=\"file\";filename=\""
                    + fileName + "\"\r\n");
            sb.append("Content-Type:application/octet-stream\r\n\r\n");

            byte[] head = sb.toString().getBytes(recvEncoding);

            // 获得输出流
            OutputStream out = new DataOutputStream(url_con.getOutputStream());
            // 输出表头
            out.write(head);
            // 文件正文部分
            // 把文件已流文件的方式 推入到url中
            DataInputStream in = new DataInputStream(fileIn);
            int bytes = 0;
            byte[] bufferOut = new byte[1024];
            while ((bytes = in.read(bufferOut)) != -1) {
                out.write(bufferOut, 0, bytes);
            }
            in.close();

            // 结尾部分
            byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n")
                    .getBytes(recvEncoding);// 定义最后数据分隔线

            out.write(foot);
            out.flush();
            out.close();

            InputStream iddn = url_con.getInputStream();
            BufferedReader rd = new BufferedReader(new InputStreamReader(iddn,
                    recvEncoding));
            String tempLine = rd.readLine();
            StringBuffer tempStr = new StringBuffer();
            String crlf = System.getProperty("line.separator");
            while (tempLine != null) {
                tempStr.append(tempLine);
                tempStr.append(crlf);
                tempLine = rd.readLine();
            }
            responseContent = tempStr.toString();
            rd.close();
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("网络故障", e);
        } finally {
            if (url_con != null) {
                url_con.disconnect();
            }
        }
        return responseContent;
    }

    /**
     * 将参数转换成string
     *
     * @param paramMap
     * @param requestEncoding
     * @return
     * @throws UnsupportedEncodingException
     */
    private static String getMapParamsToStr(Map paramMap, String requestEncoding)
            throws IOException {
        StringBuffer params = new StringBuffer();
        // 设置边界
        for (Iterator iter = paramMap.entrySet().iterator(); iter.hasNext(); ) {
            Entry element = (Entry) iter.next();
            params.append(element.getKey().toString());
            params.append("=");
            if (null!=element.getValue()){
                params.append(URLEncoder.encode(element.getValue().toString(),
                        requestEncoding));
            }else{
                params.append(URLEncoder.encode(""));
            }
            params.append("&");
        }

        if (params.length() > 0) {
            params = params.deleteCharAt(params.length() - 1);
        }

        return params.toString();
    }

    /**
     * <pre>
     * 发送带参数的GET的HTTP请求
     * </pre>
     *
     * @param reqUrl     HTTP请求URL
     * @param parameters 参数映射表
     * @return HTTP响应的字符串
     */
    public static String downMadGet(String reqUrl, Map parameters,
                                    String recvEncoding, String filePath, String media_id) {
        HttpURLConnection url_con = null;
        String responseContent = null;
        try {
            url_con = doHttpGetConnection(reqUrl, parameters);
            String fileContentType = url_con.getHeaderField("Content-Type");
            InputStream in = url_con.getInputStream();
            if ("text/plain".equals(fileContentType)) {
                BufferedReader rd = new BufferedReader(new InputStreamReader(
                        in, recvEncoding));
                responseContent = rd.readLine();
                rd.close();
            } else {
                String fileSuffix = WeiXinReqUtil
                        .getFileSuffix(fileContentType);
                BufferedInputStream bis = new BufferedInputStream(in);
                String fileName = media_id + "." + fileSuffix;
                String filePathName = filePath + File.separator + fileName;
                byte[] buf = new byte[8096];
                OutputStream fileOut = new FileOutputStream(new File(
                        filePathName));
                int size = 0;
                while ((size = bis.read(buf)) != -1) {
                    fileOut.write(buf, 0, size);
                }
                fileOut.flush();
                fileOut.close();
                bis.close();
                responseContent = "{filepath:'" + filePath + "',fileName:'"
                        + fileName + "'}";
            }
            System.out.println(fileContentType);
            in.close();
        } catch (IOException e) {
            logger.error("网络故障", e);
        } finally {
            if (url_con != null) {
                url_con.disconnect();
            }
        }

        return responseContent;
    }

    /**
     * <pre>
     * 发送带参数的GET的HTTP请求
     * </pre>
     *
     * @param reqUrl     HTTP请求URL
     * @param parameters 参数映射表
     * @return HTTP响应的字符串
     */
    public static String downMadGetQiniu(String reqUrl, String filePath,
                                         Map parameters, String prefix, Cosconfig cosconfig) {
        String responseContent = null;
        HttpURLConnection url_con = null;
        JSONObject rtnJson = new JSONObject();
        try {
            url_con = doHttpGetConnection(reqUrl, parameters);
            String fileContentType = url_con.getHeaderField("Content-Type");
            InputStream in = url_con.getInputStream();

            BufferedInputStream bis = new BufferedInputStream(in);
            String type = HttpURLConnection.guessContentTypeFromStream(bis);
            String suffix = FileType.get(type);
            if (cosconfig.getCosType().equals("ali")) {
                CosService aliOssStorageService = new AliOssStorageService();
                rtnJson = aliOssStorageService.uploadFile(cosconfig, in, "");
            } else if (cosconfig.getCosType().equals("qcloud")) {
                int length = url_con.getContentLength();
                byte[] receData = new byte[url_con.getContentLength()];
                int readLength = 0;
                // 数据数组偏移量
                int offset = 0;
                readLength = bis.read(receData, offset, length);
                // 已读取的长度
                int readAlreadyLength = readLength;
                while (readAlreadyLength < length) {
                    readLength = bis.read(receData, readAlreadyLength, length - readAlreadyLength);
                    readAlreadyLength = readAlreadyLength + readLength;
                }
                ByteArrayInputStream array = new ByteArrayInputStream(receData);
                String content = new String(receData, "ISO-8859-1");
                String fileSuffix = WeiXinReqUtil.getFileSuffix(fileContentType);
                String fileName = "";
                String res = "";
                if (fileSuffix.equals("amr")) {//转换为MP3
                    String oldMediaPath = System.getProperty("user.dir") + "\\old." + fileSuffix;
                    String newMediaPath = System.getProperty("user.dir") + "\\news.mp3";
                    logger.info("语音旧地址:" + oldMediaPath + "语音新地址:" + newMediaPath);
                    FileOutputStream fos = new FileOutputStream(oldMediaPath);
                    fos.write(receData);
                    fos.close();
                    File newsFile = new File(newMediaPath);
                    FileUtils.changeToMp3(oldMediaPath, newMediaPath);
                    File oldFile = new File(oldMediaPath);
                    if (oldFile.exists()) {
                        oldFile.delete();
                    }
                    fileName = prefix + new Date().getTime() + ".mp3";

                    //rtnJson = qcloudStorageService.uploadFile(cosconfig, in, "");
                    newsFile.delete();
                } else {
                    String newFileName = prefix+new Date().getTime()+"."+fileSuffix;
                    UploadFileRequest uploadFileRequest = new UploadFileRequest(SystemConfig.p.getProperty("Qcloud_BUCKET_NAME"), "/weixindownload/"+newFileName, "");
                    String resd = QcloudUploadUtils.uploadStream(uploadFileRequest, array,content);
                    JSONObject resJson = JSON.parseObject(resd);
                    if(resJson.containsKey("code") && "0".equals(resJson.getString("code"))){
                        String url = resJson.getJSONObject("data").getString("access_url");
                        rtnJson.put("url",url);
                    }
                    log.info("下载图片上传到cos"+resd);
                }
                logger.info("语音上传:" + res);
            } else if (cosconfig.getCosType().equals("qiniu")) {
                CosService qiniuStorageService = new QiniuStorageService();
                rtnJson = qiniuStorageService.uploadFile(cosconfig, in, "");
            } else {
                rtnJson.put("url",uploadMedia(suffix,in, (Long) parameters.get(parameters.get("accountsId"))));
            }
            in.close();
        } catch (IOException e) {
            logger.error("网络故障", e);
        } finally {
            if (url_con != null) {
                url_con.disconnect();
            }
        }
        responseContent = "{fileName:'" + rtnJson.getString("url") + "'}";
        return responseContent;
    }

    /**
     * 上传到本地
     */
    public static String uploadMedia(String suffix,InputStream inputStream,Long accountsId){
        Map<String,Object> params = new HashedMap();
        BufferedInputStream bis = null;
        FileOutputStream fos = null;
        HttpURLConnection conn = null;
        String finalFileName = "";
        try {
            String dir = USER_IMAGES_DIR+accountsId;
            File ff = new File(dir);
            if (!ff.exists()) {
                ff.mkdir();
            }
            String fileName = UUID.randomUUID().toString();
            finalFileName = fileName + suffix;

            String realPath = dir + File.separator + finalFileName;
            params.put("localPath",realPath);
            File localFile = new File(realPath);
            if (!localFile.exists() && !localFile.isFile()) {
                FileUtils.inputstreamToFile(inputStream,localFile);
            }
        } catch (IOException e) {
            log.error("上传文件失败：{}", e.getMessage());
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    log.error("上传文件失败 IOException：{}", e.getMessage());
                }
            }

            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    log.error("上传文件失败 IOException：{}", e.getMessage());
                }
            }

            if (conn != null) {
                conn.disconnect();
            }
        }
        String mediaUrl = ImageUrlUtils.formatImageUrl(finalFileName, accountsId.toString());//文件访问URL
      return mediaUrl;
    }
    /**
     * @return 连接超时(毫秒)
     */
    public static int getConnectTimeOut() {
        return HttpRequestProxy.connectTimeOut;
    }

    /**
     * @return 读取数据超时(毫秒)
     */
    public static int getReadTimeOut() {
        return HttpRequestProxy.readTimeOut;
    }

    /**
     * @return 请求编码
     */
    public static String getRequestEncoding() {
        return requestEncoding;
    }

    /**
     * @param connectTimeOut 连接超时(毫秒)
     */
    public static void setConnectTimeOut(int connectTimeOut) {
        HttpRequestProxy.connectTimeOut = connectTimeOut;
    }

    /**
     * @param readTimeOut 读取数据超时(毫秒)
     */
    public static void setReadTimeOut(int readTimeOut) {
        HttpRequestProxy.readTimeOut = readTimeOut;
    }

    /**
     * @param requestEncoding 请求编码
     */
    public static void setRequestEncoding(String requestEncoding) {
        HttpRequestProxy.requestEncoding = requestEncoding;
    }

}
