package com.boco.nbd.wios.wx.weixin;

import com.boco.nbd.wios.manage.util.SpringContextUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * @author yong
 */
@Component
public class WeixinSignUtils {

    private static String weixinAppId;

    @Value("${weixin.appId}")
    public void setWeixinAppId(String appId){
        WeixinSignUtils.weixinAppId = appId;
    }

    private static String weixinAppSecret;

    @Value("${weixin.appSecret}")
    public void setWeixinAppSecret(String appSecret){
        WeixinSignUtils.weixinAppSecret = appSecret;
    }

    private static String h5Url;

    @Value("${url.h5}")
    public void setH5Url(String h5Url){
        WeixinSignUtils.h5Url = h5Url;
    }
	
	private final static String token = "cams_wios";
	
	/**
	 * 获取当前url
     * 当前网页的URL,不包含#及其后面部分
	 * @return
	 */
	private static String getUrl(){
        HttpServletRequest request = SpringContextUtil.getRequest();
        String url = request.getRequestURL().toString();
        if(StringUtils.isNotBlank(h5Url)) {
            url=h5Url+"/";
        }
        
        String queryString = request.getQueryString();
        if(StringUtils.isNotEmpty(queryString)){
        	return url +"?"+queryString;
        }
        return url;
    }
	
	/**
	 * 获取随机码
	 * @return
	 */
	private static String create_nonce_str() {
        return UUID.randomUUID().toString();
    }
	
	/**
	 * 获取时间戳
	 * @return
	 */
	private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
	
    private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }
    
    public static Map<String, String> sign(String jsapi_ticket, String url) {
        Map<String, String> ret = new HashMap<>(8);
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String str;
        String signature = "";
 
        //注意这里参数名必须全部小写,且必须有序
        str = "jsapi_ticket=" + jsapi_ticket +
                  "&noncestr=" + nonce_str +
                  "&timestamp=" + timestamp +
                  "&url=" + url;
 
        try
        {
            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
            crypt.reset();
            crypt.update(str.getBytes(StandardCharsets.UTF_8));
            signature = byteToHex(crypt.digest());
        }
        catch (NoSuchAlgorithmException e)
        {
            e.printStackTrace();
        }

        ret.put("url", url);
        ret.put("jsapi_ticket", jsapi_ticket);
        ret.put("nonceStr", nonce_str);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);
 
        return ret;
    }
    
    public static boolean checkSignature(String signature, String timestamp, String nonce) {  
        String[] arr = new String[] { token, timestamp, nonce };  
        // 将token、timestamp、nonce三个参数进行字典序排序  
        Arrays.sort(arr);  
        StringBuilder content = new StringBuilder();  
        for (int i = 0; i < arr.length; i++) {  
            content.append(arr[i]);  
        }  
        MessageDigest md = null;  
        String tmpStr = null;  
  
        try {  
            md = MessageDigest.getInstance("SHA-1");  
            // 将三个参数字符串拼接成一个字符串进行sha1加密  
            byte[] digest = md.digest(content.toString().getBytes());  
            tmpStr = byteToStr(digest);  
        } catch (NoSuchAlgorithmException e) {  
            e.printStackTrace();  
        }  
  
        content = null;  
        // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信  
        return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;  
    }
    
    private static String byteToStr(byte[] byteArray) {  
        String strDigest = "";  
        for (int i = 0; i < byteArray.length; i++) {  
            strDigest += byteToHexStr(byteArray[i]);  
        }  
        return strDigest;  
    }  
    
    private static String byteToHexStr(byte mByte) {  
        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };  
        char[] tempArr = new char[2];  
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];  
        tempArr[1] = Digit[mByte & 0X0F];  
  
        String s = new String(tempArr);  
        return s;  
    }
    
    
    public static Map<String, String> getParam(){
    	String ticket=WeixinHelper.getJsapiTicket(weixinAppId, weixinAppSecret);
    	String url=getUrl();
    	Map<String, String> result=sign(ticket, url);
    	
    	result.put("appId", weixinAppId);
    	
    	return result;
    }
}