package cn.com.qmth.stmms.admin.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.com.qmth.stmms.common.signature.SignatureInfo;
import cn.com.qmth.stmms.common.signature.SignatureType;

public class OnlineExamHttpUtil {

    private static Logger log = LoggerFactory.getLogger(OnlineExamHttpUtil.class);

    /** 默认的编码格式 */
    public static final String DEFAULT_CHARSET = "UTF-8";

    public static final String CONTENT_TYPE = "Content-Type";

    public static final String APPLICATION_JSON = "application/x-www-form-urlencoded;charset=utf-8";

    public static final String METHOD_POST = "POST";

    public static final String AUTH = "Authorization";

    protected String uri = null;

    protected String accessKey = null;

    protected String accessSecret = null;

    public OnlineExamHttpUtil(String accessKey, String accessSecret, String uri) {
        this.accessKey = accessKey;
        this.accessSecret = accessSecret;
        this.uri = uri;
    }

    /**
     * 
     * @param params
     *            headers参数
     * @param datas
     *            requestParams参数
     * @return
     */
    public String httpAction(Map<String, String> params, Map<String, Object> datas) {
        String result = null;
        HttpsURLConnection conn = null;
        OutputStream os = null;
        InputStream is = null;

        try {

            // 获取链接
            URL url = new URL(uri);
            conn = (HttpsURLConnection) url.openConnection();

            conn.setRequestMethod(METHOD_POST);
            conn.setRequestProperty(CONTENT_TYPE, APPLICATION_JSON);
            // 设置鉴权
            long ss = System.currentTimeMillis();
            String signature = SignatureInfo.build(SignatureType.SECRET, METHOD_POST, uri, ss, accessKey, accessSecret);
            conn.setRequestProperty(AUTH, signature);
            conn.setRequestProperty("time", String.valueOf(ss));
            // ssl
            SSLContext context = SSLContext.getInstance("SSL", "SunJSSE");
            TrustManager[] tm = new TrustManager[] { new X509TrustManager() {

                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }

                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            } };
            // 初始化
            context.init(null, tm, new java.security.SecureRandom());
            // 获取SSLSocketFactory对象
            SSLSocketFactory ssf = context.getSocketFactory();
            conn.setSSLSocketFactory(ssf);

            conn.setUseCaches(false);
            conn.setDoOutput(true);

            // 设置额外的参数
            if (params != null && !params.isEmpty()) {

                for (Map.Entry<String, String> param : params.entrySet()) {
                    conn.setRequestProperty(param.getKey(), param.getValue());
                }
            }
            // 创建链接
            conn.connect();
            // 设置请求参数
            if (datas != null) {
                StringBuilder sb = new StringBuilder();
                for (Map.Entry<String, Object> data : datas.entrySet()) {
                    sb.append(data.getKey()).append("=").append(data.getValue()).append("&");
                }
                os = conn.getOutputStream();
                os.write(sb.toString().getBytes());
                os.flush();
            }

            result = getResult(conn);
        } catch (Exception e) {
            // 操作失败
            log.error("OnlineExamHttpUtil connection error!", e);
            e.printStackTrace();
            return null;
        } finally {
            try {
                if (os != null) {
                    os.close();
                    os = null;
                }
                if (is != null) {
                    is.close();
                    is = null;
                }
            } catch (IOException e) {
                log.error("OnlineExamHttpUtil connection error!", e);
            }

            if (conn != null) {
                conn.disconnect();
                conn = null;
            }
        }

        return result;
    }

    /**
     * 获得连接请求的返回数据
     * 
     * @param conn
     * 
     * @return 字符串
     */
    private String getResult(HttpURLConnection conn) throws IOException {

        StringBuilder text = new StringBuilder();

        InputStream is = null;
        InputStreamReader sr = null;
        BufferedReader br = null;

        int code = conn.getResponseCode();

        try {
            is = code >= 400 ? conn.getErrorStream() : conn.getInputStream();

            sr = new InputStreamReader(is, DEFAULT_CHARSET);
            br = new BufferedReader(sr);

            char[] chars = new char[4096];
            int length = 0;

            while ((length = br.read(chars)) != -1) {
                text.append(chars, 0, length);
            }
        } finally {
            if (br != null) {
                br.close();
                br = null;
            }
            if (sr != null) {
                sr.close();
                sr = null;
            }
            if (is != null) {
                is.close();
                is = null;
            }
        }
        if (code >= 400) {
            throw new IOException(text.toString());
        }
        return text.toString();
    }

    public static void main(String[] args) throws IOException {
        Map<String, Object> datas = new HashMap<String, Object>();
        datas.put("examId", "99513313280946176");
        String url = "/api/open/exam/course/query";
        // OnlineExamHttpUtil subjectHttp = new OnlineExamHttpUtil("123456",
        // "123", "https://m01.online-exam-test.cn", url);
        // String subjectJson = subjectHttp.httpAction(null, datas);
        // System.out.println(subjectJson);

        datas.put("courseCode", "A0002");
        OnlineExamHttpUtil studentHttp = new OnlineExamHttpUtil("123456", "123",
                "https://m01.online-exam-test.cn/api/open/exam/record/need_mark");
        String studentJson = studentHttp.httpAction(null, datas);
        System.out.println(studentJson);

        // datas.put("id", "62212585906769920");
        // url = "https://test1.online-exam-test.cn/api/open/exam/paper/detail";
        // OnlineExamHttpUtil paperHttp = new OnlineExamHttpUtil("123456",
        // "123", url);
        // String paperJson = paperHttp.httpAction(null, datas);
        // System.out.println(paperJson);
        // ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        // IOUtils.copy(new
        // ByteArrayInputStream(subjectJson.getBytes(StandardCharsets.UTF_8)),
        // buffer);
        // byte[] data = buffer.toByteArray();
        // File target = new File("/Users/ting.yin/Desktop/test123.json");
        // target.getParentFile().mkdirs();
        // FileOutputStream ous = new FileOutputStream(target);
        // ous.write(data);
        // IOUtils.closeQuietly(ous);
    }
}
