package com.fuzamei.util.blockchain;

import gfp2p.Api;
import gfp2p.Api.Case;

import java.lang.reflect.Method;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.fuzamei.eddsa.EdDSAEngine;
import com.fuzamei.eddsa.EdDSAPrivateKey;
import com.fuzamei.eddsa.spec.EdDSANamedCurveTable;
import com.fuzamei.eddsa.spec.EdDSAParameterSpec;
import com.fuzamei.eddsa.spec.EdDSAPrivateKeySpec;
import com.fuzamei.util.ReadConfUtil;
import com.google.protobuf.ByteString;


/**
 * Created by zhengfan on 2017/7/17.
 * Explain
 */
public class ProtobufUtils {
	/**
	 * 
	* @Title: initPlatform
	* @Description: TODO 平台初始化---广发催收项目
	* @param @return
	* @return ProtobufBean
	* @author: Ma Amin
	* @date: 2017-11-16 下午2:37:39
	 */
	public static ProtobufBean initPlatform(){
		ProtobufBean protobufBean = new ProtobufBean();
		//取出最大公钥和私钥
		String pubkey = ReadConfUtil.getProperty("publicKey");	//平台最大的公钥
		String platformPrivateKey = "90b289fda1fb0439158f837bbe60cc1ec99616dd0bc6335d6fd0bf3d22888e20";	//平台公钥，随便弄一个
		String platformKey = ReadConfUtil.getProperty("privateKey");	//平台最大的私钥
		Api.RequestInitPlatform.Builder builder = Api.RequestInitPlatform.newBuilder();
		try {
        	builder.setPlatformKey(ByteString.copyFrom(HexUtil.hexString2Bytes(platformKey)));
        	builder.setInfo("平台初始化");
        	SecureRandom secureRandom = new SecureRandom();
            long instructionId = secureRandom.nextLong();	//随机数
            protobufBean.setInstructionId(instructionId);
            //将requestCreateAccount对象签名
            Api.RequestInitPlatform requestBuyServe = builder.build();
            //request携带请求信息
            Api.Request.Builder request = Api.Request.newBuilder();
            request.setInitPlatform(builder);
            request.setInstructionId(instructionId);
            request.setActionId(Api.MessageType.MsgInitPlatform);
            request.setPubkey(ByteString.copyFrom(HexUtil.hexString2Bytes(pubkey)));
            Api.Request request1 = request.build();
            //用操作者的私钥签名
            byte[] bytePrivateKey = HexUtil.hexString2Bytes(platformPrivateKey);
            //签名啊
            ByteString signByteString = getSign(request1.toByteArray(), bytePrivateKey);
            //签名后的结果也给request
            request.setSign(signByteString);
            //将携带着签名后的参数信息通过http给合约，在callback里解析
            Api.Request request2 = request.build();
            byte[] requestByte = request2.toByteArray();
//            String signdata = HexUtil.bytes2HexString(requestByte);
            String signdateBase64 = encodeBase64(requestByte);
            protobufBean.setSignature(signdateBase64);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return protobufBean;
	}
	/**
	 * 
	* @Title: ImportCaseList
	* @Description: TODO 批量导入案件
	* @param @return
	* @return ProtobufBean
	* @author: Ma Amin
	* @date: 2017-11-17 下午11:46:17
	 */
	public static ProtobufBean ImportCaseList(String pubkey,String platformPrivateKey,String uid,List<Map<String,Object>> list){
		ProtobufBean protobufBean = new ProtobufBean();
		//取出最大公钥和私钥
		/*String pubkey = ReadConfUtil.getProperty("publicKey");	//银行的公钥
		String platformPrivateKey = "90b289fda1fb0439158f837bbe60cc1ec99616dd0bc6335d6fd0bf3d22888e20";	//银行的私钥
*/		
//		String platformKey = ReadConfUtil.getProperty("privateKey");	//平台最大的私钥
		///////////////////////
		
		try {
			Api.RequestImportCaseList.Builder builder = Api.RequestImportCaseList.newBuilder();
			for(int i = 0; i < list.size(); i ++){
				Api.Case.Builder buildeee = Api.Case.newBuilder();
				buildeee.setCaseId(list.get(i).get("ajh").toString());					//案件号
				buildeee.setCaseOwner(list.get(i).get("khxm").toString());				//客户姓名
				buildeee.setCaseIdCard(list.get(i).get("zjh").toString());				//证件号
				buildeee.setContract(list.get(i).get("lxfs").toString());				//联系方式
				buildeee.setBankCard(list.get(i).get("kh").toString());					//银行卡号
				buildeee.setDebtAmount(Long.parseLong(list.get(i).get("qkje").toString()));	//欠款金额
				buildeee.setOriginalAmount(Long.parseLong(list.get(i).get("bj").toString()));	//本金
				buildeee.setFees(Long.parseLong(list.get(i).get("zdj").toString()));			//滞纳金
				buildeee.setOverdueDays(Integer.parseInt(list.get(i).get("yqts").toString()));	//逾期天数
				buildeee.setCaseArea(list.get(i).get("dqbh").toString());						//地区编号
//				buildeee.setBankId("611857");
//				buildeee.setDelayDays(1);
//				buildeee.setCompanyId("1");
//				buildeee.setBankId("1");
				
				builder.addCaseList(buildeee);
				
			}
//			
//        	builder.setPlatformKey(ByteString.copyFrom(HexUtil.hexString2Bytes(platformKey)));
//        	builder.setInfo("平台初始化");
        	SecureRandom secureRandom = new SecureRandom();
            long instructionId = secureRandom.nextLong();	//随机数
            protobufBean.setInstructionId(instructionId);
            //将requestCreateAccount对象签名
            Api.RequestImportCaseList requestBuyServe = builder.build();
            //request携带请求信息
            Api.Request.Builder request = Api.Request.newBuilder();
            request.setImportCaseList(builder);
            request.setInstructionId(instructionId);
            request.setActionId(Api.MessageType.MsgImportCaseList);
            request.setPubkey(ByteString.copyFrom(HexUtil.hexString2Bytes(pubkey)));
            
            request.setUid(uid);
            Api.Request request1 = request.build();
            //用操作者的私钥签名
            byte[] bytePrivateKey = HexUtil.hexString2Bytes(platformPrivateKey);
            //签名啊
            ByteString signByteString = getSign(request1.toByteArray(), bytePrivateKey);
            //签名后的结果也给request
            request.setSign(signByteString);
            //将携带着签名后的参数信息通过http给合约，在callback里解析
            Api.Request request2 = request.build();
            byte[] requestByte = request2.toByteArray();
//            String signdata = HexUtil.bytes2HexString(requestByte);
            String signdateBase64 = encodeBase64(requestByte);
            protobufBean.setSignature(signdateBase64);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return protobufBean;
	}
	/**
	 * 
	* @Title: ImportCase
	* @Description: TODO 循环单个导入案件
	* @param @param pubkey
	* @param @param platformPrivateKey
	* @param @param uid
	* @param @param map
	* @param @return
	* @return ProtobufBean
	* @author: Ma Amin
	* @date: 2017-11-18 下午7:47:26
	 */
	public static ProtobufBean ImportCase(String pubkey,String platformPrivateKey,String uid,Map<String,Object> map){
		ProtobufBean protobufBean = new ProtobufBean();
		Api.RequestImportCase.Builder builder = Api.RequestImportCase.newBuilder();
		try {
			builder.setCaseId(map.get("ajh").toString());					//案件号
			builder.setCaseOwner(map.get("khxm").toString());				//客户姓名
			builder.setCaseIdCard(map.get("zjh").toString());				//证件号
			builder.setContract(map.get("lxfs").toString());				//联系方式
			builder.setBankCard(map.get("kh").toString());					//银行卡号
			builder.setDebtAmount(Long.parseLong(map.get("qkje").toString()));	//欠款金额
			builder.setOriginalAmount(Long.parseLong(map.get("bj").toString()));	//本金
			builder.setFees(Long.parseLong(map.get("zdj").toString()));			//滞纳金
			builder.setOverdueDays(Integer.parseInt(map.get("yqts").toString()));	//逾期天数
			builder.setCaseArea(map.get("dqbh").toString());						//地区编号
        	
			SecureRandom secureRandom = new SecureRandom();
            long instructionId = secureRandom.nextLong();	//随机数
            protobufBean.setInstructionId(instructionId);
            //将requestCreateAccount对象签名
            Api.RequestImportCase requestBuyServe = builder.build();
            //request携带请求信息
            Api.Request.Builder request = Api.Request.newBuilder();
            request.setImportCase(builder);
            request.setInstructionId(instructionId);
            request.setActionId(Api.MessageType.MsgImportCase);
            request.setPubkey(ByteString.copyFrom(HexUtil.hexString2Bytes(pubkey)));
            
            request.setUid(uid);
            Api.Request request1 = request.build();
            //用操作者的私钥签名
            byte[] bytePrivateKey = HexUtil.hexString2Bytes(platformPrivateKey);
            //签名啊
            ByteString signByteString = getSign(request1.toByteArray(), bytePrivateKey);
            //签名后的结果也给request
            request.setSign(signByteString);
            //将携带着签名后的参数信息通过http给合约，在callback里解析
            Api.Request request2 = request.build();
            byte[] requestByte = request2.toByteArray();
//            String signdata = HexUtil.bytes2HexString(requestByte);
            String signdateBase64 = encodeBase64(requestByte);
            protobufBean.setSignature(signdateBase64);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return protobufBean;
	}
	/**
	 * 
	* @Title: updateWeight
	* @Description: TODO 更新权重
	* @param @param pubkey		--银行的公钥
	* @param @param platformPrivateKey	--银行的私钥
	* @param @param uid					--银行的uid
	* @param @return
	* @return ProtobufBean
	* @author: Ma Amin
	* @date: 2017-11-18 下午4:47:19
	 */
	public static ProtobufBean updateWeight(List<Map<String,Object>> list){
		ProtobufBean protobufBean = new ProtobufBean();
		Api.RequestUpdateWeight.Builder builder = Api.RequestUpdateWeight.newBuilder();
		try {
//        	builder.setPlatformKey(ByteString.copyFrom(HexUtil.hexString2Bytes(platformKey)));
			if(list.size() != 0){	//有数据才操作
				String pubkey = list.get(0).get("pubKey").toString();
				String platformPrivateKey =  list.get(0).get("privateKey").toString();
				String uid = list.get(0).get("uid").toString();
	        	//多个地区循环
				for(int i = 0; i < list.size(); i ++){
					Api.CompanyWeight.Builder bui = Api.CompanyWeight.newBuilder();
					bui.setArea(list.get(i).get("collectionArea").toString());
		        	bui.setCompanyId(list.get(i).get("outsourcingAgencyId").toString());
		        	bui.setWeight((int)(Double.parseDouble(list.get(i).get("weightProportion").toString())*10000));
					builder.addWeightList(bui);
				}
				SecureRandom secureRandom = new SecureRandom();
	            long instructionId = secureRandom.nextLong();	//随机数
	            protobufBean.setInstructionId(instructionId);
	            //将requestCreateAccount对象签名
	            Api.RequestUpdateWeight requestBuyServe = builder.build();
	            //request携带请求信息
	            Api.Request.Builder request = Api.Request.newBuilder();
//	            request.setInitPlatform(builder);
	            request.setUpdateWeight(builder);
	            request.setInstructionId(instructionId);
	            request.setActionId(Api.MessageType.MsgUpdateWeight);
	            request.setPubkey(ByteString.copyFrom(HexUtil.hexString2Bytes(pubkey)));
	            request.setUid(uid);
	            Api.Request request1 = request.build();
	            //用操作者的私钥签名
	            byte[] bytePrivateKey = HexUtil.hexString2Bytes(platformPrivateKey);
	            //签名啊
	            ByteString signByteString = getSign(request1.toByteArray(), bytePrivateKey);
	            //签名后的结果也给request
	            request.setSign(signByteString);
	            //将携带着签名后的参数信息通过http给合约，在callback里解析
	            Api.Request request2 = request.build();
	            byte[] requestByte = request2.toByteArray();
//	            String signdata = HexUtil.bytes2HexString(requestByte);
	            String signdateBase64 = encodeBase64(requestByte);
	            protobufBean.setSignature(signdateBase64);
			}
        } catch (Exception e) {
            e.printStackTrace();
        }
        return protobufBean;
	}

    private static ByteString getSign(byte[] requestByte, byte[] bytePrivateKey) {
        EdDSAParameterSpec spec = EdDSANamedCurveTable.getByName("Ed25519");
        byte[] signbyte = new byte[0];
        try {
            Signature sgr = new EdDSAEngine(MessageDigest.getInstance(spec.getHashAlgorithm()));
            EdDSAPrivateKeySpec privKey = new EdDSAPrivateKeySpec(bytePrivateKey, spec);
            PrivateKey sKey = new EdDSAPrivateKey(privKey);
            sgr.initSign(sKey);
            sgr.update(requestByte);
            signbyte = sgr.sign();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (SignatureException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        return ByteString.copyFrom(signbyte,0,64);
    }
    public static String encodeBase64(byte[]input) throws Exception{  
        Class clazz=Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");  
        Method mainMethod= clazz.getMethod("encode", byte[].class);  
        mainMethod.setAccessible(true);  
         Object retObj=mainMethod.invoke(null, new Object[]{input});  
         return (String)retObj;  
    }  

}

