package com.gary.msr.proto;

import java.util.Arrays;

import android.content.Context;
import android.hardware.usb.UsbManager;
import android.util.Log;

import com.gary.msr.DataChangeListener;
import com.gary.msr.hid.USBOp;
//import com.gary.msr.proto.MSRLayerParams.MSRLayer1Params;
//import com.gary.msr.proto.MSRLayerParams.MSRLayer2Params;

/*
 * JAVA层数据均采用int[]数数组，传到JNI C/C++层时需要转换成unsigned char[]
 */
public class MSRPacket {
	public static int[] PACKET = new int[9 * 1024];
	// 报文头
	public static final byte REPORT_ID = 0x08;
	// 第一层数据长度
	public static final int MSR_LAYER1_LEN = 30;
	// 命令字: 进入\退出测试模式
	public static final byte CMD_MODEL = 0x2E;
	public static final byte DATA_MODEL_ENTER = 0x00;
	public static final byte DATA_MODEL_EXIT = 0x01;
	// 命令字: 写配置
	public static final byte CMD_MSR_WRITE = 0x2A;
	// 命令字: 读配置
	public static final byte CMD_MSR_READ = 0x29;
	public static final byte DATA_MSRCONFIG = 0x7E;
	// 命令字: IC卡上电
	public static final byte CMD_IC_POWERON = 0x26;
	public static final byte DATA_ICPOWERON = 0x00;
	// 命令字: IC卡下电
	public static final byte CMD_IC_POWEROFF = 0x25;
	public static final byte DATA_ICPOWEROFF = 0x00;
	// 命令字: IC卡APDU
	public static final byte CMD_IC_APDU = 0x27;
	// 命令字: 读取版本信息
	public static final byte CMD_VERSION = 0x2d;

	// 返回时正确的状态码
	public static final byte CMD_RESPONSE_DEFAULT = 0x30;
	
	public USBOp mUSBOp;

	///20190822 添加构造函数
	public MSRPacket(UsbManager manager,Context context, String AppName)
	{
		
		mUSBOp= new USBOp(manager,context,AppName);
		if(!mUSBOp.UsbFeatureSupported()){
			Log.e("gary", "设备不支持USBHOST");
		}
		//mUSBOp.SetUsbConfig(0x0603, 0x096e, 0x03, 0x01, 0x02);
		//mUSBOp.SetUsbConfig( 0x8238,0x10c4, 0x03, 0x01, 0x02);
		mUSBOp.SetUsbConfig( 0x8235,0x10c4, 0x03, 0x01, 0x02);
		//mUSBOp.SetUsbConfig( 0x847c,0x10c4, 0x03, 0x01, 0x02);
		//mUSBOp.SetUsbConfig( 0x0005,0x0901, 0x03, 0x00, 0x00);
		
		
	}
	
	// 构造发送数据

	// 层数据,或其他数据 到待发送的数据
	public static int buildPackge(int cmd, int[] configData, int dataLen) {
		clear();
		PACKET[0] = REPORT_ID;
		PACKET[1] = cmd;
		PACKET[2] = ((dataLen >> 8) & 0xff);
		PACKET[3] = (dataLen & 0xff);
		if (cmd == CMD_MSR_WRITE || cmd == CMD_MSR_READ) {
			PACKET[3] = ((dataLen + 1) & 0xff);
			PACKET[2] = (((dataLen + 1) >> 8) & 0xff);
			PACKET[4] = DATA_MSRCONFIG;
			if (configData != null && dataLen > 0)
				System.arraycopy(configData, 0, PACKET, 5, dataLen);
			return (5 + dataLen);
		}
		if (configData != null && dataLen > 0) {
			System.arraycopy(configData, 0, PACKET, 4, dataLen);
			return (4 + dataLen);
		} else {
			return 2;
		}
	}

	// 解析返回数据到层数据，或其他数据
	public static int resolveConfigData(int[] configData) {
		int configDataLen = PACKET[3] | (PACKET[2] << 8);
		if (configDataLen > 0 && configData != null) {
			System.arraycopy(PACKET, 4, configData, 0, configDataLen);
		}
		return PACKET[1];
	}

	private static void clear() {
		// for (int i = 0; i < PACKET.length; i++) {
		// PACKET[i] = 0;
		// }
		Arrays.fill(PACKET, 0);
	}

	// 协议1, 进入/退出测试模式
	public boolean protoTestMode(boolean enterFlag) {
		int n = enterFlag ? DATA_MODEL_ENTER : DATA_MODEL_EXIT;
		int[] data = { n };
		int buildLen = buildPackge(CMD_MODEL, data, data.length);
		// ret 为实际收到长度，此处不做检验
		int ret = mUSBOp.sendDataMsr(PACKET, buildLen);
		if (ret < 0)
			return false;
		int flag = resolveConfigData(null);
		return (flag == CMD_RESPONSE_DEFAULT);
	}

	// 协议2, 写配置
	public boolean protoWriteConfig() {
		int[] configData = new int[9 * 1024];
		int configLen = MSRProto.constructMSRConfigData(configData);
		Log.e("gary", "protoWriteConfig configLen: " + configLen);
		int buildLen = buildPackge(CMD_MSR_WRITE, configData, configLen);
		Log.e("gary", "protoWriteConfig buildLen: " + buildLen);
		// ret 为实际收到长度，此处不做检验
		int ret = mUSBOp.sendDataMsr(PACKET, buildLen);
		Log.e("gary", "protoWriteConfig ret: " + ret);
		if (ret < 0)
			return false;
		int flag = resolveConfigData(null);
		return (flag == CMD_RESPONSE_DEFAULT);
	}

	// 协议3, 读配置
	public boolean protoReadConfig(int[] configData) {
		// int configLen = MSRProto.constructMSRConfigData(configData);
		int buildLen = buildPackge(CMD_MSR_READ, null, 0);
		if (buildLen < 0)
			return false;
		// ret 为实际收到长度，此处不做检验
		int ret = mUSBOp.sendDataMsr(PACKET, buildLen);
		if (ret < 0)
			return false;
		int flag = resolveConfigData(configData);
		return (flag == CMD_RESPONSE_DEFAULT);
	}

	// 协议4, IC卡上电
	public boolean protoICPowerup(DataChangeListener listener) {
		int[] data = { DATA_ICPOWERON };
		int buildLen = buildPackge(CMD_IC_POWERON, data, data.length);
		if (listener != null)
			listener.dataSndChanged(USBOp.convert2String(PACKET, buildLen));
		int ret = mUSBOp.sendDataMsr(PACKET, buildLen);
		if (ret < 0)
			return false;
		listener.dataRcvChanged(USBOp.convert2String(PACKET, ret));
		listener.dataFlagChanged(Integer.toHexString(PACKET[1]));
		int flag = resolveConfigData(null);
		return (flag == CMD_RESPONSE_DEFAULT);
	}

	// 协议5, IC卡下电
	public  boolean protoICPowerdown(DataChangeListener listener) {
		int[] data = { DATA_ICPOWEROFF };
		int buildLen = buildPackge(CMD_IC_POWEROFF, data, data.length);
		if (listener != null)
			listener.dataSndChanged(USBOp.convert2String(PACKET, buildLen));
		int ret = mUSBOp.sendDataMsr(PACKET, buildLen);
		if (ret < 0)
			return false;
		listener.dataRcvChanged(USBOp.convert2String(PACKET, ret));
		listener.dataFlagChanged(Integer.toHexString(PACKET[1]));
		int flag = resolveConfigData(null);
		return (flag == CMD_RESPONSE_DEFAULT);
	}

	// 协议6, APDU
	public static int[] parseLetersToIntArr(String hexString) {
		int len = 0, strLen = 0;
		strLen = hexString.length();
		len = (strLen % 2 == 0) ? (strLen / 2) : (strLen / 2 + 1);
		int data[] = new int[len];
		String tmpStr = hexString;
		if (strLen % 2 == 1)
			tmpStr += "0";
		for (int i = 0; i < len; i++) {
			String s = tmpStr.substring(2 * i, 2 * i + 2);
			try {
				data[i] = Integer.parseInt(s, 16);
			} catch (Exception e) {
				e.printStackTrace();
				return null;
			}
		}
		return data;

	}

	public boolean protoAPDU(String str, DataChangeListener listener) {
		int[] data = parseLetersToIntArr(str);
		if (data == null)
			return false;
		int buildLen = buildPackge(CMD_IC_APDU, data, data.length);
		if (listener != null)
			listener.dataSndChanged(USBOp.convert2String(PACKET, buildLen));
		int ret = mUSBOp.sendDataMsr(PACKET, buildLen);
		if (ret < 0)
			return false;
		listener.dataRcvChanged(USBOp.convert2String(PACKET, ret));
		listener.dataFlagChanged(Integer.toHexString(PACKET[1]));
		int flag = resolveConfigData(null);
		return (flag == CMD_RESPONSE_DEFAULT);
	}

	// 协议7, 版本信息
	//public static int protoVersion(int[] configData) {
	public int protoVersion(int[] configData) {
		int buildLen = buildPackge(CMD_VERSION, null, 0);
		// ret 为实际收到长度，此处不做检验
		int ret = mUSBOp.sendDataMsr(PACKET, buildLen);
		if (ret < 0)
			return ret;

		int configDataLen = PACKET[3] | (PACKET[2] << 8);
		if (configDataLen > 0 && configData != null) {
			System.arraycopy(PACKET, 4, configData, 0, configDataLen);
			return configDataLen;
		}
		return -1;
	}
}
