package com.example.administrator.wingcool_gt9_apk;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.hardware.usb.UsbRequest;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.InputType;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.net.DatagramPacket;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Timer;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class IICOperation extends AppCompatActivity
        implements  OpenDevicesReceiver.OpenDevicesListener, View.OnClickListener{

    private Context mAlertContext;

    private static final int CONNECTED_SUCCESS = 0;
    private static final int RECEIVER_MESSAGE_SUCCESS = 1;
    private static final int SEND_MESSAGE_SUCCESS = 2;
    private static final int DEBUG_MESSAGE_SUCCESS = 3;
    private static final int DEBUG_MESSAGE_ERROR = 4;

    private static final String USB_ACTION = "com.host2device";
    private static final String ACTION_USB_PERMISSION = "com.host2device.USB_PERMISSION";
    private ExecutorService mThreadPool;
    private UsbManager mUsbManager;
    private OpenDevicesReceiver iicOpenDevicesReceiver;
    private UsbDeviceConnection mUsbDeviceConnection;
    private UsbEndpoint mUsbEndpointOut;
    private UsbEndpoint mUsbEndpointIn;

    private byte[] mBytes = new byte[1024];
    private byte[] mSendData = new byte[1024];
    private byte[] mConfigData = new byte[1024];
    private String[] mVersionShow = new String[7];
    private String[] mDataShow = new String[1024];

    private boolean isReceiverMessage = true;
    private boolean isSendMessage = true;

    private boolean isNeedFindDevice  = true;

    private boolean bottonMode = false;
    private int iReadDataTimes = 0;

    private UsbInterface mUsbInterface;
    private StringBuilder stringBuilderShow = new StringBuilder("");
    private Context mContext;

    private Button btnReadData;
    private Button btnWriteData;

    private EditText edtDataShow;
    private EditText edtDataWrite;
    private EditText edtAddressInput;
    private EditText edtLengthInput;

    private CheckBox cbDualBytes;
    private CheckBox cbSequentialRead;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_iic_operation);
        mAlertContext = IICOperation.this;
        ConstantsActivity.activityList.add(this);
        //switchLanguage(ConstantsActivity.langae);

        InitButton();
        InitEditText();
        InitListener();
        InitCheckBox();
        InitData();

        openDevices();
    }

    //核心设置的代码
    protected void switchLanguage(String language) {
        Resources resources = getResources();
        Configuration config = resources.getConfiguration();
        DisplayMetrics dm = resources.getDisplayMetrics();
        switch (language) {
            case "zh":
                config.locale = Locale.CHINESE;
                resources.updateConfiguration(config, dm);
                break;
            case "en":
                config.locale = Locale.ENGLISH;
                resources.updateConfiguration(config, dm);
                break;
            default:
                config.locale = Locale.US;
                resources.updateConfiguration(config, dm);
                break;
        }
    }

    private void InitButton(){
        btnReadData = (Button) findViewById(R.id.readdata);
        btnWriteData = (Button) findViewById(R.id.writedata);
    }

    private void InitEditText(){
        edtDataShow = (EditText) findViewById(R.id.datashow);
        edtDataWrite = (EditText) findViewById(R.id.datawrite);
        edtAddressInput = (EditText) findViewById(R.id.addressinput);
        edtLengthInput = (EditText) findViewById(R.id.lengthinput);

        edtDataShow.setKeyListener(null);
    }

    private void InitListener(){
        btnReadData.setOnClickListener(this);
        btnWriteData.setOnClickListener(this);
    }

    private void InitCheckBox(){
        cbDualBytes = (CheckBox) findViewById(R.id.dualbytes);
        cbSequentialRead = (CheckBox) findViewById(R.id.sequentialread);
    }

    private void InitData(){
        mContext = getApplicationContext();
        btnReadData.setEnabled(false);
        btnWriteData.setEnabled(false);

        mThreadPool = Executors.newFixedThreadPool(5);

        mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
    }

    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {

            int lengthtemp;
            StringBuilder stringBuilderShowTemp = new StringBuilder("");
            String value;
            String hv;

            if (edtLengthInput.getText().length() == 0 || edtLengthInput.getText().toString() == "0") {
                lengthtemp = 1;
            }else{
                lengthtemp = Integer.parseInt(edtLengthInput.getText().toString(),10);
            }

            switch (msg.what) {
                case CONNECTED_SUCCESS://车机和手机连接成功
                    btnReadData.setEnabled(true);
                    btnWriteData.setEnabled(true);
                    break;

                case RECEIVER_MESSAGE_SUCCESS://成功接受到数据
                    if (bottonMode == false){
                        edtDataShow.setText( stringBuilderShow.toString() );//输出显示
                        //edtDataShow.requestFocus();
                        edtDataShow.setSelection(edtDataShow.getText().length());
                        stringBuilderShow = new StringBuilder("");
                        iReadDataTimes = 0;
                        break;
                    }
                    iReadDataTimes++;
                    stringBuilderShow.append("【"+ Integer.toString(iReadDataTimes) +"】");
                    stringBuilderShowTemp.append("【"+ Integer.toString(iReadDataTimes) +"】");

                    for (int i = 0; i < lengthtemp; i++) {
                        int k = mBytes[i] & 0xFF;

                        value = Integer.toHexString(k);
                        if (value.length() < 2) {
                            value = "0" + value;
                        }

                        if (cbDualBytes.isChecked()){    //双字节显示
                            int l = mBytes[i + 1] & 0xFF;
                            hv = Integer.toHexString(l);
                            if (hv.length() < 2) {
                                hv = "0" + hv;
                            }
                            value = hv + value;

                            i++;
                        }

                        value = "0x" + value;
                        stringBuilderShow.append(value);
                        stringBuilderShow.append("  ");

                        stringBuilderShowTemp.append(value);
                        stringBuilderShowTemp.append("  ");
                    }
                    stringBuilderShow.append("\n");
                    stringBuilderShowTemp.append("\n");
                    edtDataShow.setText( stringBuilderShowTemp.toString() );//输出显示
                    //edtDataShow.requestFocus();
                    edtDataShow.setSelection(edtDataShow.getText().length());
                    break;

                case SEND_MESSAGE_SUCCESS://成功发送数据

                    break;

                case DEBUG_MESSAGE_SUCCESS://成功发送数据

                    break;

                default:
                    break;
            }
        }
    };

    @Override
    public void onClick(final View view) {

        int lengthtemp;
        byte addressH, addressL;
        StringBuilder stringBuilder = new StringBuilder("");
        String value;
        String hv;

        if (edtAddressInput.getText().length() < 3){
            Toast.makeText(this, getResources().getString(R.string.enteraddress), Toast.LENGTH_SHORT).show();
            return;
        }else{
            addressH = (byte)((Integer.parseInt(edtAddressInput.getText().toString(),16) >> 8) & 0xFF);
            addressL = (byte)(Integer.parseInt(edtAddressInput.getText().toString(),16) & 0xFF);
        }

        if (edtLengthInput.getText().length() == 0 || edtLengthInput.getText().toString() == "0") {
            lengthtemp = 1;
        }else{
            lengthtemp = Integer.parseInt(edtLengthInput.getText().toString(),10);
        }

        switch (view.getId()) {
            case R.id.readdata:     //read
                if (cbSequentialRead.isChecked()){    //连续读取

                    if (bottonMode == false){
                        bottonMode = true;
                        btnReadData.setText(getResources().getString(R.string.stop));
                        sequentialRead();
                    }else{
                        bottonMode = false;
                        btnReadData.setText(getResources().getString(R.string.readdata));
                    }

                    break;
                }

                bottonMode = false;

                iicRead(addressH,addressL,mBytes,lengthtemp);

                for (int i = 0; i < lengthtemp; i++) {

                    int k = mBytes[i] & 0xFF;

                    value = Integer.toHexString(k);
                    if (value.length() < 2) {
                        value = "0" + value;
                    }

                    if (cbDualBytes.isChecked()){    //双字节显示
                        int l = mBytes[i + 1] & 0xFF;
                        hv = Integer.toHexString(l);
                        if (hv.length() < 2) {
                            hv = "0" + hv;
                        }
                        value = hv + value;

                        i++;
                    }

                    value = "0x" + value;
                    stringBuilder.append(value);
                    stringBuilder.append("  ");
                }

                edtDataShow.setText( stringBuilder.toString() );//输出显示
                break;

            case R.id.writedata:    //write
                value = edtDataWrite.getText().toString();
                String[] stringArr = value.split(" ");

                byte[] mBufferData = new byte[1024];
                for (int i = 0; i < stringArr.length; i++) {
                    byte aByte = (byte) Integer.parseInt(stringArr[i], 16);
                    mBufferData[i] = aByte;
                }

                iicWrite(addressH,addressL,mBufferData,0,lengthtemp);

                Toast.makeText(this,"Send successfully",Toast.LENGTH_SHORT).show();
                break;

            default:
                break;
        }
    }

    private void sequentialRead() {
        mThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                int lengthtemp;
                byte addressH, addressL;

                addressH = (byte)((Integer.parseInt(edtAddressInput.getText().toString(),16) >> 8) & 0xFF);
                addressL = (byte)(Integer.parseInt(edtAddressInput.getText().toString(),16) & 0xFF);

                if (edtLengthInput.getText().length() == 0 || edtLengthInput.getText().toString() == "0") {
                    lengthtemp = 1;
                }else{
                    lengthtemp = Integer.parseInt(edtLengthInput.getText().toString(),10);
                }

                while(true) {
                    if (iicRead(addressH,addressL,mBytes,lengthtemp)){
                        mHandler.sendEmptyMessage(RECEIVER_MESSAGE_SUCCESS);
                    }

                    SystemClock.sleep(20);

                    if (bottonMode == false){ //停止读取之后重新初始化
                        stringBuilderShow = new StringBuilder("");
                        iReadDataTimes = 0;
                        break;
                    }

                }
            }
        });
    }

    /**
     * 打开设备 , 让车机和手机端连起来
     */
    private void openDevices() {

        //列举设备(手机)
        iicOpenDevicesReceiver = new OpenDevicesReceiver(this);
        mThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                SystemClock.sleep(1000);
                PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), 0);
                IntentFilter intentFilter = new IntentFilter(USB_ACTION);

                registerReceiver(iicOpenDevicesReceiver, intentFilter);
                while(isNeedFindDevice) {
                    SystemClock.sleep(100);
                    HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
                    if (deviceList != null) {
                        for (UsbDevice usbDevice : deviceList.values()) {
                            //int productId = usbDevice.getProductId();
                            int vendorId = usbDevice.getVendorId();
                            if ((vendorId == 0x27C0)          //之前VID错误了，做兼容
                                    ||(vendorId == 0x27C6)    //汇顶的VID
                                    ||(vendorId == 0x222A)    //奕力的VID
                                    ||(vendorId == 0x056A))   //8191主动笔和Wacom主动笔
                            {

                                if (mUsbManager.hasPermission(usbDevice)) {

                                    initDevice();

                                } else {
                                    mUsbManager.requestPermission(usbDevice, pendingIntent);
                                    break;
                                }
                                break;
                            }
                        }
                    } else {
                        //mError.setText("请连接USB");
                    }
                    // }
                }
            }   //ThreadPool
        });   //ThreadPool
    }

    /**
     * 初始化设备(手机) , 当手机进入Accessory模式后 , 手机的PID会变为Google定义的2个常量值其中的一个 ,
     */
    private void initDevice() {

        HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
        Collection<UsbDevice> values = deviceList.values();
        if (!values.isEmpty()) {
            for (UsbDevice usbDevice : values) {
                //int productId = usbDevice.getProductId();
                int vendorId = usbDevice.getVendorId();
                //if (productId == 0x0818 || productId == 0x0001 )
                if ((vendorId == 0x27C0)          //之前VID错误了，做兼容
                        ||(vendorId == 0x27C6)    //汇顶的VID
                        ||(vendorId == 0x222A)    //奕力的VID
                        ||(vendorId == 0x056A))   //8191主动笔和Wacom主动笔
                {

                    if (mUsbManager.hasPermission(usbDevice)) {

                        UsbInterface usbInterface = usbDevice.getInterface(1);

                        for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
                            UsbEndpoint ep = usbInterface.getEndpoint(i);

                            if (ep.getDirection() == UsbConstants.USB_DIR_OUT) {
                                //mUsbEndpointIn = ep;
                                mUsbEndpointOut = ep;
                            } else {
                                //mUsbEndpointOut = ep;
                                mUsbEndpointIn = ep;
                            }
                        }

                        if ((null == mUsbEndpointIn) || (null == mUsbEndpointOut)) {
                            mUsbDeviceConnection = mUsbManager.openDevice(usbDevice);
                            if (mUsbDeviceConnection!=null) {
                                int i = mUsbDeviceConnection.controlTransfer(0x00, 0x09,
                                        0x002, 0, null, 0, 100);
                                SystemClock.sleep(1000);
                                if (i >= 0) {
                                    //mHandler.sendEmptyMessage(DEBUG_MESSAGE_SUCCESS);
                                } else {
                                    //mHandler.sendEmptyMessage(DEBUG_MESSAGE_ERROR);
                                }
                            }
                        } else {
                            isNeedFindDevice = false;
                            mUsbInterface = usbInterface;
                            mUsbDeviceConnection = mUsbManager.openDevice(usbDevice);
                            mUsbDeviceConnection.claimInterface(mUsbInterface, true);
                            if(null != mUsbEndpointIn){
                                mHandler.sendEmptyMessage(CONNECTED_SUCCESS);
                            }
                        }
                    } else {
                        mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(""), 0));
                    }
                }
            }
        } else {
            // finish();
        }
    }

    private byte iicByteData[]={
            //0    1   2     3    4    5    6
            0x03,0x00,0x0f,0x00,0x00,0x00,0x01,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

    };
    private byte iicWriteData[]={
            //0    1   2     3    4    5    6
            0x03,0x00,0x0f,0x00,0x00,0x00,0x39,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
            0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

    };

    //发送命令，使得S818可以通过IIC向GT9的固定地址读取任意bytes的数据
    private boolean iicRead(byte addressHigh,byte addressLow,byte[] wBuffer,int length) {

        int i;

        iicByteData[1] = 0x00; //read GT9 command
        iicByteData[2] = 0x0f; //no command
        iicByteData[3] = addressHigh;
        iicByteData[4] = addressLow;
        iicByteData[5] = 0x00;
        iicByteData[6] = 63;  //length 一次接收63个数据

        for (int j = 7; j < 64; j++) {
            iicWriteData[j] = 0x00;
        }

        int address1 = ((addressHigh&0xff)<<8);
        int address2 = addressLow&0xff;
        int address = address1|address2;

        int sendTimes = length/63 + 1;  //预计是向下取整，所以+1

        iicByteData[5] = (byte)(length>>8);
        iicByteData[6] = (byte)length;  //length 一次接收63个数据

        //发送读取命令
        i = mUsbDeviceConnection.bulkTransfer(mUsbEndpointOut, iicByteData, 0, 0x40, 100);
        if (i != 0x40)
            return false;  //传输失败

        for (int k = 0; k < sendTimes; k++) {
            //int finalOffset = k*63; //每次只能发57bytes数据
            int offset = k*64;

          //  if(length - (finalOffset ) < 63) {

               // iicByteData[6] = (byte) (length - (finalOffset));  //length
           // }
         //   else
         //   {
              //  iicByteData[6] = 63;
          //  }


           // SystemClock.sleep(1);

            isReceiverMessage = false;  //先关闭循环接收信息

           //接收数据
           // i = mUsbDeviceConnection.bulkTransfer(mUsbEndpointIn, wBuffer, offset, 0x40, 100);
            i = mUsbDeviceConnection.bulkTransfer(mUsbEndpointIn, wBuffer, offset, 0x40, 100);

            //if (i != 0x40) {
            if (i != 0x40) {
               // mError.setText("iicWrite Failed");
                //Update_log = "iicRead Failed";
                mHandler.sendEmptyMessage(DEBUG_MESSAGE_ERROR);
                return false;

            }

           // address = address + 63;
          //  iicByteData[3] = (byte)(address>>8);
          //  iicByteData[4] = (byte)address;
        }

        //将report id从数组中去除
        //byte[] temperBuffer =new byte[length];
        if(true) {
            int count1 = 0;
            for (int k = 0; k < length; k++) {
                if (k % 63 == 0) {
                    count1++;
                }

                wBuffer[k] = wBuffer[k + count1];

            }
        }
        return true;
    }
    //发送命令，使得S818可以通过IIC向GT9的固定地址写任意bytes的数据
    private  boolean iicWrite(byte addressHigh,byte addressLow,byte[] wBuffer,int offset,int length) {
        int i;

        iicWriteData[1] = 0x01; //write GT9 command
        iicWriteData[2] = 0x0f; //no command
        iicWriteData[3] = addressHigh;
        iicWriteData[4] = addressLow;
        iicWriteData[5] = 0x00;
        iicWriteData[6] = 0x39;  //length

        int address1 = ((addressHigh&0xff)<<8);
        int address2 = addressLow&0xff;
        int address = address1|address2;

        int sendTimes = length/57 + 1;  //预计是向下取整，所以+1

        for (int k = 0; k < sendTimes; k++) {
            int finalOffset = offset + k*57; //每次只能发57bytes数据

            if(length - (finalOffset -offset) < 57) {

                iicWriteData[6] = (byte) (length - (finalOffset -offset));  //length
            }
            else
            {
                iicWriteData[6] = 0x39;
            }

            for (int j = 7; j < 64; j++) {
                iicWriteData[j] = wBuffer[finalOffset + j -7];
            }
            i = mUsbDeviceConnection.bulkTransfer(mUsbEndpointOut, iicWriteData, 0, 0x40, 100);

            if (i != 0x40) {
              //  mError.setText("iicWrite Failed");
                //Update_log = "iicWrite Failed";
                mHandler.sendEmptyMessage(DEBUG_MESSAGE_ERROR);
                return false;

            }

            address = address + 57;
            iicWriteData[3] = (byte)(address>>8);
            iicWriteData[4] = (byte)address;
        }

        return true;
    }

    //发送命令，使得S818可以通过IIC向GT9的固定地址写1byte数据
    private  boolean iicByteWrite(byte addressHigh,byte addressLow,byte subCommand,byte data) {
        int i;

        iicByteData[1] = 0x01; //write GT9 command
        iicByteData[2] = subCommand;
        iicByteData[3] = addressHigh;
        iicByteData[4] = addressLow;
        iicByteData[5] = 0x00;
        iicByteData[6] = 0x01;  //length

        iicByteData[7] = data;
        if ((null == mUsbEndpointIn) || (null == mUsbEndpointOut)){
            i = 0;
            //mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
           // initDevice();
            i = mUsbDeviceConnection.bulkTransfer(mUsbEndpointOut, iicByteData, 0, 0x40, 100);
        }
        else {
            i = mUsbDeviceConnection.bulkTransfer(mUsbEndpointOut, iicByteData, 0, 0x40, 100);
        }
        // i = 0;
        if(i == 0x40)
            return true;
        else
            return false;
    }

    private boolean iicTest() {
        if(isReceiverMessage)
            return false;

        return true;
    }

    //发送命令，使得S818可以通过IIC向GT9的固定地址读取1byte数据
    private byte iicByteRead(byte addressHigh,byte addressLow) {
        iicByteData[1] = 0x00; //read GT9 command
        iicByteData[2] = 0x0f;  //no command
        iicByteData[3] = addressHigh;
        iicByteData[4] = addressLow;
        iicByteData[5] = 0x00;   //length
        iicByteData[6] = 0x01;   //lengthlow

        iicByteData[7] = 0x00;
        //  mThreadPool.execute(new Runnable() {
        //     @Override
        //     public void run() {
        int i;
        boolean byteReceiverLoop = true;
        i = mUsbDeviceConnection.bulkTransfer(mUsbEndpointOut, iicByteData, 0, 0x40, 100);
        if (i != 0x40)
            return 0x77;  //用0x77来表示传输失败
        //SystemClock.sleep(5);

        isReceiverMessage = false;  //先关闭循环接收信息


        i = mUsbDeviceConnection.bulkTransfer(mUsbEndpointIn, mBytes, 0, 0x40, 3000);
        //SystemClock.sleep(5);
        if (i == 0x40)
            return mBytes[1];
        else
            return 0x77;  //用0x77来表示传输失败
        // }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (mUsbDeviceConnection != null) {
            mUsbDeviceConnection.releaseInterface(mUsbInterface);
            mUsbDeviceConnection.close();
            mUsbDeviceConnection = null;
        }
        mUsbEndpointIn = null;
        mUsbEndpointOut = null;
        //mToggle = false;
        isReceiverMessage = false;
        isNeedFindDevice = false;
        mThreadPool.shutdownNow();
        // unregisterReceiver(mUsbDetachedReceiver);
        unregisterReceiver(iicOpenDevicesReceiver);
    }
}
