package com.yyrh.utils;

import android.util.Base64;

import java.io.ByteArrayOutputStream;
import java.net.URLEncoder;
import java.security.Key;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Collections;

import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import static com.yyrh.constant.URLConstants.APP_KEY;

public class SignUtils {

    private static final int MAX_ENCRYPT_BLOCK = 117;
    public static final String KEY_ALGORITHM = "RSA";

    public static String encryptParam(HashMap<String,String> map) {
        String paramContent = "";
        String URLenCodeparamContent = "";
        List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(map.entrySet());
        Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
            @Override
            public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                return o1.getKey().compareTo(o2.getKey());
            }
        });

        for (int i = 0; i < infoIds.size(); i++) {

            String id =  infoIds.get(i).toString();
            paramContent = paramContent + id + "&";
        }

        String time = System.currentTimeMillis() / 1000 + "";
        String allParam = paramContent + "time=" + time + "qDikI9v?>!x)1rS&yo";
        String sign = Utils.getMD5(allParam);

        for (String key : map.keySet()) {
            YYLog.i(key + "=" + map.get(key));
            URLenCodeparamContent = URLenCodeparamContent + key + "=" + toURLEncoded(map.get(key)) + "&";
           }

        URLenCodeparamContent =URLenCodeparamContent + "time=" + time  + "&sign="+ sign ;
        return URLenCodeparamContent;
    }

    public static String paramSign(HashMap<String,String> map) {
        String paramContent = "";
        List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(map.entrySet());
        Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
            @Override
            public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                return o1.getKey().compareTo(o2.getKey());
            }
        });

        for (int i = 0; i < infoIds.size(); i++) {

            String id =  infoIds.get(i).toString();
            paramContent = paramContent + id + "&";
        }

        String time = toURLEncoded(System.currentTimeMillis() / 1000 + "");
        paramContent = Utils.getMD5(paramContent + "time=" + time + "qDikI9v?>!x)1rS&yo");
        return paramContent;
    }

    public static String encryptRsaByPublicKey(String key, String text)
            throws Exception {

        // 对公钥解密
        byte[] data = Base64.decode(key, Base64.NO_WRAP);



        byte[] byteText = text.getBytes();
        // 取得公钥
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(data);
        KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
        Key publicKey = keyFactory.generatePublic(x509KeySpec);

        // 对数据加密
        Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);

        int inputLen = byteText.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        while (inputLen -offSet > 0 ){
            if(inputLen -offSet >MAX_ENCRYPT_BLOCK){
                cache = cipher.doFinal(byteText,offSet,MAX_ENCRYPT_BLOCK);
            }else{
                cache = cipher.doFinal(byteText,offSet,inputLen - offSet);
            }
            out.write(cache,0,cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();


        String strBase64 = new String(Base64.encode(encryptedData, Base64.NO_WRAP));

        return strBase64;
    }

    public static String toURLEncoded(String paramString) {
        if (paramString == null || paramString.equals("")) {
            return "";
        }

        try {
            String str = new String(paramString.getBytes(), "UTF-8");
            str = URLEncoder.encode(str, "UTF-8");
            return str;
        } catch (Exception localException) {
            System.out.println("toURLEncoded error:" + paramString + ","
                    + localException);
        }

        return "";
    }



    public static String paramSign(HashMap<String,String> map ,String time) {
        String paramContent = "";
        List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(map.entrySet());
        Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
            @Override
            public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                return o1.getKey().compareTo(o2.getKey());
            }
        });

        for (int i = 0; i < infoIds.size(); i++) {

            String id =  infoIds.get(i).toString();
            paramContent = paramContent + id + "&";



        }
        String content = paramContent +"time=" + time + "qDikI9v?>!x)1rS&yo";

        paramContent = getMD5(content);
        return paramContent;
    }


    public static String getMD5(String content) {
        String s = null;
        char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
                'a', 'b', 'c', 'd', 'e', 'f'};
        try {
            java.security.MessageDigest md = java.security.MessageDigest
                    .getInstance("MD5");
            md.update(content.getBytes());
            byte tmp[] = md.digest();
            char str[] = new char[16 * 2];
            int k = 0;
            for (int i = 0; i < 16; i++) {
                byte byte0 = tmp[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            s = new String(str);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return s;
    }

    /**
     * 新融合增加打点上报签名规则
     */

    public static String sdkLogParamSign(HashMap<String,String> map) {
        String paramContent = "";
        List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(map.entrySet());
        Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
            @Override
            public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                return o1.getKey().compareTo(o2.getKey());
            }
        });

        for (int i = 0; i < infoIds.size(); i++) {

            String id =  infoIds.get(i).toString();
            paramContent = paramContent + id + "&";


        }
        String sign = "";
        paramContent = paramContent.substring(0,paramContent.length() - 1);
        try {
            sign = hmacSHA256(paramContent,APP_KEY);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return sign;
    }

    public static String hmacSHA256(String data, String key) throws Exception {

        Mac sha256_HMAC = Mac.getInstance("HmacSHA256");

        SecretKeySpec secret_key = new SecretKeySpec(key.getBytes("UTF-8"), "HmacSHA256");

        sha256_HMAC.init(secret_key);

        byte[] array = sha256_HMAC.doFinal(data.getBytes("UTF-8"));

        StringBuilder sb = new StringBuilder();

        for (byte item : array) {

            sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));

        }

        return sb.toString();

    }



    public static String sdkLogEncryptParam(HashMap<String,String> map) {
        String paramContent = "";
        String URLenCodeparamContent = "";
        List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(map.entrySet());
        Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
            @Override
            public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                return o1.getKey().compareTo(o2.getKey());
            }
        });

        for (int i = 0; i < infoIds.size(); i++) {

            String id =  infoIds.get(i).toString();
            paramContent = paramContent + id + "&";
        }



        String sign = sdkLogParamSign(map);

        for (String key : map.keySet()) {
            YYLog.i(key + "=" + map.get(key));
            URLenCodeparamContent = URLenCodeparamContent + key + "=" + toURLEncoded(map.get(key)) + "&";
        }

        URLenCodeparamContent =URLenCodeparamContent  + "sign="+ sign ;
        return URLenCodeparamContent;
    }

    /*
     **************************************************** 上报log日志签名工具
     */


    /**
     * 将byte转为16进制
     *
     * @param bytes
     * @return
     */
    private static String byte2Hex(byte[] bytes) {
        StringBuffer stringBuffer = new StringBuffer();
        String temp = null;
        for (int i = 0; i < bytes.length; i++) {
            temp = Integer.toHexString(bytes[i] & 0xFF);
            if (temp.length() == 1) {
                //1得到一位的进行补0操作
                stringBuffer.append("0");
            }
            stringBuffer.append(temp);
        }
        return stringBuffer.toString();
    }






    public static String sha256Hex(String s) throws Exception {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] d = md.digest(s.getBytes("UTF-8"));
        return  byte2Hex(d).toLowerCase();
    }


    public static byte[] hmac256(byte[] key, String msg) throws Exception {
        Mac mac = Mac.getInstance("HmacSHA256");
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, mac.getAlgorithm());
        mac.init(secretKeySpec);
        return mac.doFinal(msg.getBytes("UTF-8"));
    }


    /*
     * 签名
     */
    public static String sdkLogParamSign(String time, String value) {
        String sha256_value = null;
        try {
            sha256_value = sha256Hex(value);
        } catch (Exception e) {
            e.printStackTrace();
        }


        String sign = "timestamp=" + time + "\n" + sha256_value;

        String hmac_sha256_value = "";
        try {

            hmac_sha256_value = byte2Hex(hmac256(APP_KEY.getBytes("UTF-8"), sign)).toLowerCase();;


        } catch (Exception e) {
            e.printStackTrace();
        }

        return hmac_sha256_value;
    }



}

