package com.synjones.idcardusb_reader;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;

import com.synjones.DeviceConnectManager;
import com.synjones.m1card.M1CardReader;
import com.synjones.multireaderlib.MultiReader;
import com.synjones.util.util;


public class ReadM1CardActivity extends Activity {
    private Button BtnFindCard;
    private Button BtnVerifyKeyA;
    private Button BtnVerifyKeyB;
    private Button BtnReadBlock;
    private Button BtnWrite;
    private Button BtnPending;
    private Button BtnClear;
    private ScrollView svResult;
    //private Button BtnWriteBlocks;
    //private Button BtnReadBlocks;
    private TextView tvMsg;

    private byte data[]=new byte[1024];//接收buf
    private int dataLen=0;//接收数据长度
    private static final String TAG="M1Card";
    public M1CardReader m1Reader;
    MultiReader multiReader= MultiReader.getReader();
    DeviceConnectManager deviceConnectManager= DeviceConnectManager.getInstance();
    long time=0;
    final  int MESSAGE_FIND_CARD=0x51;
    boolean findingCard=false;
    Activity activity;
    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MESSAGE_FIND_CARD:
                    BtnFindCard.setEnabled(true);
                    if(data==null)
                        return;
                   // beep();
                    //Toast.makeText(activity, "find a Card", Toast.LENGTH_SHORT).show();
                    if(dataLen!=0) {
                        tvMsg.append("寻卡成功！\r\n");
                        M1CardInfo m1CardInfo=new M1CardInfo(data);
                        TextView tvStatus=(TextView) activity.findViewById(R.id.tvStatus);
                        tvStatus.setText(m1CardInfo.toString());
                    }
                    else
                        tvMsg.append("寻卡失败！\r\n");

                    scroll();
                    break;

            }
        }
    };


    public ReadM1CardActivity() {
        // Required empty public constructor
    }


    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.fragment_read_m1_card);
        initViews();
    }

    public void initViews() {
        time=System.currentTimeMillis();
        activity=this;
        svResult=(ScrollView) findViewById(R.id.scrollMsg);
        BtnFindCard	=(Button) activity.findViewById(R.id.btnFind);
        BtnVerifyKeyA 	=(Button) activity.findViewById(R.id.btnVerifyKeyA);
        BtnVerifyKeyB	=(Button) activity.findViewById(R.id.btnVerifyKeyB);
        BtnReadBlock=(Button) activity.findViewById(R.id.btnReadblock);
        BtnWrite	=(Button) activity.findViewById(R.id.btnWrite);
        BtnClear	=(Button) activity.findViewById(R.id.btnClear);
        BtnPending  =(Button) activity.findViewById(R.id.btnPending);
        //BtnWriteBlocks=(Button) activity.findViewById(R.id.btnWriteBlocks);
        //BtnReadBlocks=(Button) activity.findViewById(R.id.btnReadBlocks);
        tvMsg=(TextView) activity.findViewById(R.id.tvMsg);
        //MainActivity.Reader.getReaderDriver().EnterWorkModeNoReply();
        BtnFindCard.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(!deviceConnectManager.isOpen()){
                    deviceConnectManager.open();
                }
                if(deviceConnectManager.isOpen()){
                    if(m1Reader==null) {
                        multiReader.setDataTransInterface(deviceConnectManager.getDataTransChannel());
                        m1Reader = new M1CardReader(multiReader);
                    }
                    FindCard(5000);
                    BtnFindCard.setEnabled(false);
                }
            }
        });

        BtnVerifyKeyA.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                boolean ret=DownloadKey(M1CardReader.KeyType.KeyA, getBlock(), getKey());
                tvMsg.append(ret?"验证成功":getRedText("验证失败"));
                scroll();
            }
        });
        BtnVerifyKeyB.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                //ReadBlock(getBlock(),getKey(),KeyTypeB);
                boolean ret=DownloadKey(M1CardReader.KeyType.KeyB, getBlock(), getKey());
                tvMsg.append(ret?"验证成功":getRedText("验证失败"));
                scroll();
            }
        });

        BtnReadBlock.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                long t=System.currentTimeMillis();
                byte reta[]=ReadBlock(getBlock());
                if(reta!=null)
                    tvMsg.append(util.bytesToHexString(reta));
                else
                    tvMsg.append(getRedText("读失败"));
                tvMsg.append("用时："+(System.currentTimeMillis()-t)+"\r\n");
                scroll();
            }
        });
        BtnWrite.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                boolean ret=WriteBlock(getBlock(),getWritedata());
                tvMsg.append("写块 "+getBlock()+"结果："+(ret==true?"成功":getRedText("失败"+"\r\n")));
                scroll();
            }
        });

        BtnPending.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                boolean ret=PendingCard();
                if(ret)
                    tvMsg.append("挂起成功");
                else
                    tvMsg.append(getRedText("挂起失败"));
                scroll();
            }
        });
        BtnClear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                tvMsg.setText("");
                TextView tvs=(TextView) activity.findViewById(R.id.tvStatus);
                tvs.setText("状态");
            }
        });


        deviceConnectManager.open();


   /*    BtnWriteBlocks.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                if(isConnect){
                    if(m1Reader==null)
                        m1Reader=new M1CardReader(multiReader);
                    writeBlocks();
                }
            }
        });

        BtnReadBlocks.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View arg0) {
                if(isConnect){
                    if(m1Reader==null)
                        m1Reader=new M1CardReader(multiReader);
                    readBlocks();
                }
            }
        });*/


    }


    @Override
    public void onDestroy() {
        super.onDestroy();
    }




    /**
     * 寻卡
     */
    public void FindCard(final int timeout){
        findingCard=true;
        new Thread(new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub
                byte recv[]=null;
                long t=System.currentTimeMillis();
                dataLen=0;
                //multiReader.EnterWorkMode();
                while(findingCard && System.currentTimeMillis()-t<timeout&& recv==null){
                    recv=m1Reader.findM1Card();
                    if(recv!=null)
                    {
                        System.arraycopy(recv, 0, data, 0, recv.length);
                        dataLen=recv.length;
                        mHandler.sendEmptyMessage(MESSAGE_FIND_CARD);
                        break;
                    }
                }
                findingCard=false;
                if(recv==null)
                    mHandler.sendEmptyMessage(MESSAGE_FIND_CARD);

            }
        }).start();
    }

    /**
     * 写卡
     * @param blockNo
     * 块号
     * @param data
     * 16字节数据
     */
    public boolean WriteBlock(byte blockNo,byte data[]){
        if(m1Reader==null) return false;
        return m1Reader.writeBlock(blockNo, data);

    }




    /**
     * 获取界面上输入的KEY
     * @return
     */
    public byte[] getKey(){
        byte key[]=new byte[6];
        EditText et;
        int KeyId= R.id.etKey0;
        for(int i=0;i<6;i++){
            et=(EditText) activity.findViewById(KeyId+i);
            String hexStr="0x"+et.getText().toString();
            try{
                int tmp=Integer.decode(hexStr);
                key[i]=(byte)(tmp&0xff);
            }catch(Exception e){
                String err="getKey() err"+e.getMessage();
                d(this,err);
                Toast.makeText(activity, err, Toast.LENGTH_SHORT).show();

            }
        }
        return key;
    }
    /**
     * 获取界面上输入的data
     * @return
     */

    public byte[] getWritedata(){
        int dataId[]={R.id.etWriteData0, R.id.etWriteData1, R.id.etWriteData2, R.id.etWriteData3,
                R.id.etWriteData4, R.id.etWriteData5, R.id.etWriteData6, R.id.etWriteData7,
                R.id.etWriteData8, R.id.etWriteData9, R.id.etWriteData10, R.id.etWriteData11,
                R.id.etWriteData12, R.id.etWriteData13, R.id.etWriteData14, R.id.etWriteData15};
        byte Writedata[]=new byte[16];
        EditText et;
        //int dataId=R.id.etWriteData0;
        for(int i=0;i<16;i++){
            et=(EditText) activity.findViewById(dataId[i]);
            String hexStr="0x"+et.getText().toString();
            try{
                int tmp=Integer.decode(hexStr);
                Writedata[i]=(byte)(tmp&0xff);
            }catch(Exception e){
                String err="getKey() err"+e.getMessage();
                d(this,err);
                Toast.makeText(activity, err, Toast.LENGTH_SHORT).show();

            }
        }
        return Writedata;
    }

    public static void d(Object o,String msg){
        Log.d(TAG,o.getClass().getName()+" "+msg);
    }
    public static void e(Object o,String msg){
        Log.e(TAG,o.getClass().getName()+" "+msg);
    }
    /**
     * 获取界面上的块号
     * @return
     */
    public byte getBlock(){
        EditText et=(EditText) activity.findViewById(R.id.etBlock);
        String BlockStr=et.getText().toString();
        int tmp=0;
        try{
            tmp=Integer.decode(BlockStr);
        }catch(Exception e){
            d(this,"getKey() err"+e.getMessage());

        }
        return (byte)(tmp&0xff);
    }

    private int getTestBlockNums(){
        EditText et=(EditText) activity.findViewById(R.id.etTestNums);
        String BlockStr=et.getText().toString();
        int tmp=0;
        try{
            tmp=Integer.decode(BlockStr);
        }catch(Exception e){
            d(this,"getKey() err"+e.getMessage());
        }
        return tmp;
    }


    /**
     * 显示卡片类型信息
     * @param buf
     * 接收到的数据buf
     * @param len
     * 接收到的数据长度
     */
    public void showCardInfo(byte buf[],int len)
    {
        if(len>0 && buf[0]==0xa){
            TextView tvStatus=(TextView) activity.findViewById(R.id.tvStatus);
            String status="|卡号："+bytesToHexString(getCardNo(buf), 4)+"|类型："+bytesToHexString(getCardType(buf), 2)
                    +"|大小："+bytesToHexString(getCardSize(buf), 1);
            tvStatus.setText(status);
        }
    }
    /**
     * 从寻卡返回的数据中获取卡号
     * @param buf
     * 接收到的数据
     * @return
     */
    public byte[] getCardNo(byte buf[]){
        if(buf[0]==0x03 || buf[0]!=0x0a) return null;
        byte cardNo[]=new byte[4];
        int cardNOoffset=2;
        System.arraycopy(buf,cardNOoffset, cardNo, 0, cardNo.length);
        return cardNo;
    }

    /**
     * 获取卡片类型
     * @param buf
     * 接收到的数据
     * @return
     */
    public byte[] getCardType(byte buf[]){
        if(buf[0]==0x03 || buf[0]!=0x0a) return null;
        byte cardType[]=new byte[2];
        int cardTypeoffset=6;
        System.arraycopy(buf,cardTypeoffset, cardType, 0, cardType.length);
        return cardType;
    }
    /**
     * 获取卡大小
     * @param buf
     * 接收到的数据
     * @return
     */
    public byte[] getCardSize(byte buf[]){
        if(buf[0]==0x03 || buf[0]!=0x0a) return null;
        int cardTypeoffset=8;
        byte cardSize[]=new byte[1];
        cardSize[0]=buf[cardTypeoffset];
        return cardSize;
    }



    public void onResume() {
        d(this,TAG+   "Enter onResume");
        super.onResume();
    }


    public static String bytesToHexString(byte[] src,int len){
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < len; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            stringBuilder.append("0x");
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }

            stringBuilder.append(hv.toUpperCase());
            stringBuilder.append(",");
        }
        return stringBuilder.toString();
    }


    public  boolean PendingCard(){
        if(m1Reader==null) return false;
        return m1Reader.pend();
    }

    //下载密钥A
    public  boolean DownloadKey(M1CardReader.KeyType keytype, byte block, byte key[]){
		/*下载扇区密钥A*/
        if(m1Reader==null) return false;
        return m1Reader.verifyKey(keytype, block, key);
    }


    /**
     * 读卡片上的block数据
     * @param block
     * 需要读取的block块
     * @return
     * 读到的卡片上的块数据
     */
    public  byte[] ReadBlock(byte block){
        if(m1Reader==null) return null;
        return m1Reader.readBlock(block);
    }

    public void scroll(){

        svResult.post(new Runnable() {
            public void run() {
                svResult.fullScroll(ScrollView.FOCUS_DOWN);
            }
        });
    }




    public void beep(){
        //byte cmdarray[]=packCMD(CMDtype.beep,null);
        //newserial.SendData(cmdarray, cmdarray.length);
        //if(Is_ok(recvdata,len))
        //Toast.makeText(getActivity(), "len="+len, Toast.LENGTH_SHORT).show();
        //tvMsg.append(bytesToHexString(data,dataLen));

    }
/*
    private void writeBlocks(){
        if(m1Reader==null) return;
        tvMsg.setText("");
        TextView tvs=(TextView) activity.findViewById(R.id.tvStatus);
        tvs.setText("状态");
        WriteBlocksAsync wba=new WriteBlocksAsync();
        wba.execute();
    }
    private void readBlocks(){
        if(m1Reader==null) return;
        tvMsg.setText("");
        TextView tvs=(TextView) activity.findViewById(R.id.tvStatus);
        tvs.setText("状态");
        ReadBlocksAsnnc rba=new ReadBlocksAsnnc();
        rba.execute();
    }*/

    private boolean findCard(long timeout){
        long t=System.currentTimeMillis();
        //multiReader.EnterWorkMode();
        while(System.currentTimeMillis()-t<timeout){
            byte recv[]=m1Reader.findM1Card();
            if(recv!=null)
            {
                return true;
            }
        }
        return false;
    }


    private SpannableStringBuilder getRedText(String text){
        return getColorText(text, Color.RED);
    }
    private SpannableStringBuilder getColorText(String text,int color){
        SpannableStringBuilder builder = new SpannableStringBuilder(text);
        //ForegroundColorSpan 为文字前景色，BackgroundColorSpan为文字背景色 Color.RED
        ForegroundColorSpan redSpan = new ForegroundColorSpan(color);
        builder.setSpan(redSpan, 0, text.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        return builder;
    }

    /*private class ReadBlocksAsnnc extends AsyncTask<Void, Integer, Integer> {
        //byte readdata[][]=new byte[16][16];
        byte readBlockData[];
        long startTime;
        CmdResponse resp=null;
        int num=0;
        @Override
        protected void onPreExecute() {
            // TODO Auto-generated method stub
            super.onPreExecute();
            BtnReadBlocks.setEnabled(false);
            num=getTestBlockNums();
        }
        @Override
        protected Integer doInBackground(Void... arg0) {
            byte blockNo= getBlock();
            boolean needDownKey=true;
            boolean ret=false;
            byte key[]=getKey();
            startTime=System.currentTimeMillis();
            if(!findCard(1000))
                return -2;
            // m1Reader.beginTrans();
            for(int pos=0;pos<num;pos++){
                //genWriteData(pos);
                if((blockNo+1)%4==0){
                    blockNo++;
                    needDownKey=true;
                }
                //needDownKey=true;
                int intBlockNo=((int)blockNo)&0xff;
                publishProgress(0,intBlockNo);
                if(needDownKey){
                    ret=DownloadKey(M1CardReader.KeyType.KeyA, blockNo, key);
                    if(!ret) publishProgress(-1,intBlockNo);
                    needDownKey=false;
                }
                //long t1=System.currentTimeMillis();

                readBlockData=ReadBlock(blockNo);
                if(readBlockData!=null && verifyData(0,readBlockData)){
                    publishProgress(2,intBlockNo);
                }else{
                    publishProgress(1,intBlockNo);
                }
                blockNo++;
                //sleep(10);
            }
            long t1=System.currentTimeMillis();
            return 0;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            // TODO Auto-generated method stub
            super.onProgressUpdate(values);
            switch (values[0]) {
                case -1:
                    tvMsg.append(getRedText("第"+values[1]+"块密钥验证失败\r\n"));
                    break;
                case 0:
                    tvMsg.append("第"+values[1]+"块测试读开始"+*//*bytesToHexString(writedata[pos],16)*//*"\r\n");
                    //Log.e("m1", "第"+values[1]+"块测试写开始"+bytesToHexString(writedata[pos],16)+"\r\n");
                    break;
                case 1:
                    tvMsg.append(getRedText("第"+values[1]+"块读出数据失败\r\n"));
                    break;
                case 2:
                    tvMsg.append("第"+values[1]+"块读卡成功,数据="+bytesToHexString(readBlockData,16)+"\r\n");
                    break;
                case 4:
                    tvMsg.append("用时："+values[1]+"mS\r\n");
                    break;
                default:
                    break;
            }
        }
        @Override
        protected void onPostExecute(Integer result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);
            BtnReadBlocks.setEnabled(true);
            super.onPostExecute(result);
            switch (result) {
                case 0:
                    tvMsg.append("测试结束\r\n"+"用时："+(System.currentTimeMillis()-startTime));
                    SparseArray<byte[]> readArray= m1Reader.getReadData(resp);
                    if(resp!=null){
                        tvMsg.append("\r\n数据="+bytesToHexString(resp.getData(), resp.getData().length)+"\r\n");
                    }
                    break;
                case -1:
                    tvMsg.append(getRedText("测试失败\r\n"));
                    break;
                case -2:
                    tvMsg.append(getRedText("寻卡失败"));
                    break;
                default:
                    break;
            }
        }

    }




    private class WriteBlocksAsync extends AsyncTask<Void, Integer, Integer>{
        private byte writedata[][]=new byte[16][16];
        private int pos;
        private long startTime;
        int num=0;
        @Override
        protected void onPreExecute() {
            // TODO Auto-generated method stub
            super.onPreExecute();
            BtnWriteBlocks.setEnabled(false);
            num=getTestBlockNums();
        }
        @Override
        protected Integer doInBackground(Void... arg0) {
            byte blockNo= getBlock();
            boolean needDownKey=true;
            boolean ret=false;
            byte key[]=getKey();
            startTime=System.currentTimeMillis();
            if(!findCard(1000))
                return -2;
            //m1Reader.beginTrans();
            for(pos=0;pos<num;pos++){
                //genWriteData(pos);
                if((blockNo+1)%4==0){
                    blockNo++;
                    needDownKey=true;
                }
                int intBlockNo=((int)blockNo)&0xff;
                publishProgress(0,intBlockNo);
                if(needDownKey){
                    ret=DownloadKey(M1CardReader.KeyType.KeyA, blockNo, key);
                    if(!ret) publishProgress(-1,intBlockNo);
                    needDownKey=false;
                }
                //	long t1=System.currentTimeMillis();
                ret=WriteBlock(blockNo,getWritedata());
                if(!ret) publishProgress(-2,intBlockNo);
                else publishProgress(3,intBlockNo);
                blockNo++;
                //sleep(10);
            }

            return 0;
        }
        @Override
        protected void onProgressUpdate(Integer... values) {
            // TODO Auto-generated method stub
            super.onProgressUpdate(values);
            switch (values[0]) {
                case -1:
                    tvMsg.append(getRedText("第"+values[1]+"块密钥验证失败\r\n"));
                    break;
                case -2:
                    tvMsg.append(getRedText("第"+values[1]+"块写卡失败\r\n"));
                    break;
                case 0:
                    tvMsg.append("第"+values[1]+"块测试写开始"+*//*bytesToHexString(writedata[pos],16)*//*"\r\n");
                    //Log.e("m1", "第"+values[1]+"块测试写开始"+bytesToHexString(writedata[pos],16)+"\r\n");
                    break;
                case 3:
                    tvMsg.append("第"+values[1]+"块写卡成功\r\n");
                    break;
                case 4:
                    tvMsg.append("用时："+values[1]+"mS\r\n");
                    break;
                default:
                    break;
            }
        }

        @Override
        protected void onPostExecute(Integer result) {
            // TODO Auto-generated method stub
            BtnWriteBlocks.setEnabled(true);
            super.onPostExecute(result);
            switch (result) {
                case 0:
                    //CmdResponse resp=m1Reader.endTrans(1000);

                    tvMsg.append("测试结束\r\n"+"用时："+(System.currentTimeMillis()-startTime));
                    // if(resp!=null)
                    //     tvMsg.append("\r\n测试写成功\r\n");
                    break;
                case -1:
                    tvMsg.append(getRedText("测试失败\r\n"));
                    break;
                case -2:
                    tvMsg.append(getRedText("寻卡失败"));
                    break;
                default:
                    break;
            }
        }

        private void genWriteData(int index){
            for(int i=0;i<16;i++){
                writedata[index][i]=(byte) (Math.random()*256);
            }
        }


        private void sleep(long t) {
            try {
                Thread.sleep(t);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }


    }*/

    private boolean verifyData(int index,byte data[]){
        byte wd[]=getWritedata();
        for(int i=0;i<16;i++){
            if(wd[i]!=data[i])
                return false;
        }
        return true;
    }
}