package org.bdware.sc.http;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class HttpUtil {
    static final String RESPONSE = "__response";
    protected static String BOUNDARY = "DHFKJSHIDSKFSDFSFDS";

    public static Map<String, Object> httpGet(String str) {
        Map<String, Object> ret = new HashMap<>();

        try {
            URL url = new URL(str);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setConnectTimeout(40000);
            connection.setReadTimeout(40000);
            ret.put("responseCode", connection.getResponseCode());
            InputStream input = connection.getInputStream();
            Scanner sc = new Scanner(input);
            StringBuilder sb = new StringBuilder();
            while (sc.hasNextLine()) {
                sb.append(sc.nextLine()).append("\n");
            }
            sc.close();
            ret.put("response", sb.toString());
        } catch (Throwable e) {
            ret.put("responseCode", 505);
            ByteArrayOutputStream bo = new ByteArrayOutputStream();
            e.printStackTrace(new PrintStream(bo));
            ret.put("response", bo.toString());
        }
        return ret;
    }

    public static String postForm(String baseUrl, Map<String, String> header, File f) {
        HttpURLConnection connection = null;
        try {
            URL url = new URL(baseUrl);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("POST");
            for (String key : header.keySet()) connection.setRequestProperty(key, header.get(key));
            connection.setDoOutput(true);
            connection.setDoInput(true);
            OutputStream out = connection.getOutputStream();
            //	ByteArrayOutputStream out = new ByteArrayOutputStream();
            out.write(("\r\n--" + BOUNDARY + "\r\n").getBytes(StandardCharsets.UTF_8));
            String resSB = "Content-Disposition: form-data; name=\"file\";" +
                    " filename=\"" +
                    (f.getName()) +
                    "\r\n\r\n";
            out.write(resSB.getBytes(StandardCharsets.UTF_8));

            // 开始写文件
            DataInputStream in = new DataInputStream(new FileInputStream(f));
            int bytes = 0;
            byte[] bufferOut = new byte[1024 * 5];
            while ((bytes = in.read(bufferOut)) != -1) {
                // out.write(bufferOut, 0, bytes);
            }
            out.write("Hello".getBytes());
            out.write(("\r\n--" + BOUNDARY + "--\r\n").getBytes(StandardCharsets.UTF_8));
            in.close();
            out.close();

            InputStream input = connection.getInputStream();
            Scanner sc = new Scanner(input);
            StringBuilder sb = new StringBuilder();
            while (sc.hasNextLine()) {
                sb.append(sc.nextLine()).append("\n");
            }
            sc.close();
            return sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
            if (null != connection) {
                InputStream error = connection.getErrorStream();
                Scanner sc = new Scanner(error);
                StringBuilder sb = new StringBuilder();
                while (sc.hasNextLine()) {
                    sb.append(sc.nextLine()).append("\n");
                }
                System.out.println(sb);
            }
        }
        return "failed";
    }

    public static String request(
            String baseUrl,
            String method,
            Map<String, String> header,
            Map<String, String> argMap,
            List<String> reservedList) {
        switch (method.toUpperCase()) {
            case "GET":
            case "POST":
            case "DELETE":
            case "PUT":
                System.out.println("baseUrl:" + baseUrl + " method:" + method);
                Map<String, String> r = http(method, baseUrl, getParamStr(argMap), header);
                return r.get(RESPONSE);
            default:
                return "Unsupported RequestMethod:" + method;
        }
    }

    private static String getParamStr(Map<String, String> argMap) {
        if (argMap.keySet().size() == 0) return "";
        StringBuilder sb = new StringBuilder();
        sb.append("?");
        boolean isFirst = true;
        for (String key : argMap.keySet()) {
            sb.append(isFirst ? "?" : "&").append(argMap.get(key));
            isFirst = false;
        }
        return sb.toString();
    }

    public static Map<String, String> http(
            String app, String str, String param, Map<String, String> props) {
        HttpURLConnection connection;
        Map<String, String> result = new HashMap<>();
        try {
            URL url = new URL(str);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod(app);
            for (String key : props.keySet()) connection.setRequestProperty(key, props.get(key));
            connection.setDoOutput(true);
            connection.setDoInput(true);
            if (param.length() > 0) {
                connection.getOutputStream().write(param.getBytes());
                connection.getOutputStream().flush();
            }
            loadHeader(result, connection);
            InputStream input = connection.getInputStream();

            Scanner sc = new Scanner(input);
            StringBuilder sb = new StringBuilder();
            while (sc.hasNextLine()) {
                sb.append(sc.nextLine()).append("\n");
            }
            sc.close();
            result.put(RESPONSE, sb.toString());
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new HashMap<>();
    }

    private static void loadHeader(Map<String, String> result, HttpURLConnection connection) {
        try {
            for (String key : connection.getHeaderFields().keySet()) {
                result.put(key, connection.getHeaderField(key));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
