package com.xixun.communicate;

import com.xixun.communicate.Protocol.NET_COMMU_TYPE;
import com.xixun.communicate.Protocol.StreamPort;
import com.xixun.display.MyLog;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.Socket;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Created by Administrator on 16/11/9.
 */

public class TcpCommunication{
    private Socket socket=null;
    private String clientIpAddress=null;
    ClientManage clientManage=null;
    public DataInputStream receStream=null;
    public DataOutputStream sendStream=null;

    public static StreamPort streamPort = null;
   
    TcpCommunication(ClientManage clientManage,Socket socket)
    {   this.clientManage=clientManage;
        this.socket=socket;
        clientIpAddress=clientManage.GetIpAddress();//socket.getInetAddress().getHostAddress();

	    new Thread() {
            public void run() {
                Process();
            }
        }.start();
    }

	private void Process() {
 		try {
				receStream=new DataInputStream(socket.getInputStream());
				sendStream=new DataOutputStream(socket.getOutputStream());

                streamPort = new StreamPort(clientIpAddress,true,new IFunctionCallBack() {
                    @Override
                    public void LastSendDataProcess(byte[] DataBuffer, int iLength) {
                        LastTransProcess(DataBuffer,iLength);
                    }
                    @Override
                    public void LastReceDataProcess(byte[] DataBuffer, int iLength) {
                        LastReceProcess();
                    }
                });

                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try{
                            ReceCommand();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
				bReady=true;
        }catch (Exception e) {
				//if (NeedExit()==false || GetReady())
					MyLog.i(clientIpAddress+ " "+ Thread.currentThread().getStackTrace()[2].getFileName() + "-->"
							+   "Function: " +Thread.currentThread().getStackTrace()[2].getMethodName() + "-->"
							+   "Line" +Thread.currentThread().getStackTrace()[2].getLineNumber() + ":\r\n"
							+   "    Error:" + e.getMessage() + "\r\n\r\n"
					);
        }

        while (NeedExit() == false)
        {
            try
            {
                Thread.sleep(ClientsManage.HEART_INTERVAL);
                TransData_Byte(NET_COMMU_TYPE.TICK.getValue(),(byte)0,(byte)0,null, 0); // 周期发送随意数据，用于检测链路状态，检测链接是否通讯正常。
            }
            catch (Exception e)
            {   //if (NeedExit() == false)
                    MyLog.i(clientIpAddress+ " "+ Thread.currentThread().getStackTrace()[2].getFileName() + "-->"
                        + "Function: " + Thread.currentThread().getStackTrace()[2].getMethodName() + "-->"
                        + "Line" + Thread.currentThread().getStackTrace()[2].getLineNumber() + ":\r\n"
                        + "    Error:" + e.getMessage() + "\r\n\r\n"
                );
                break;
            }

            Tick_Counter();    //  iCounter++;
            if (Tick_TimeOut())
            {   MyLog.i("---------------------Time Out.");
                break;
            }

        }
        MyLog.i(clientIpAddress+ " " + Thread.currentThread().getStackTrace()[2].getFileName() + "-->"
                + "Function: " + Thread.currentThread().getStackTrace()[2].getMethodName() + "-->"
                + "Line" + Thread.currentThread().getStackTrace()[2].getLineNumber() + ":\r\n"
        );
        Stop();
    }


    int iCounter = 0;
    public void Tick()
    {
        iCounter = 0;
    }

    void Tick_Counter()
    {
        iCounter++;
   //     MyLog.i("Tick_Counter = " +iCounter);
    }

    Boolean Tick_TimeOut()
    {
        return (iCounter > 6);
    }

    public void TransData_Byte(byte ucCommand,byte ucIdence, byte ucPipeId, byte[] DataBuffer, int iLength)
    {
        if (NeedExit()) return;

        if (streamPort!=null)
            streamPort.TransData_Byte(ucCommand,ucIdence, ucPipeId,DataBuffer,iLength);
    }


    private void ReceCommand() {
        byte[]  receDataBuffer=new byte[StreamPort.MAX_PACKET_SIZE+256];

       // MyLog.i("--------------------------fw");

        while (NeedExit()==false) {
            int iReceLenth=0;
            if (socket==null) break;
            if (socket.isConnected()==false) break;

            if (GetReady()==false) break;
            if (sendStream==null) break;
            try {
                iReceLenth=receStream.read(receDataBuffer);
             //   MyLog.i("--------------------------iReceLenth = "+iReceLenth);
            } catch (Exception e) {
                //if (NeedExit()==false ||GetReady())
                    MyLog.i(clientIpAddress+ " "+ Thread.currentThread().getStackTrace()[2].getFileName() + "-->"
                        + "Function: " + Thread.currentThread().getStackTrace()[2].getMethodName() + "-->"
                        + "Line" + Thread.currentThread().getStackTrace()[2].getLineNumber() + ":\r\n"
                        + "    Error:" + e.getMessage() + "\r\n\r\n"
                );
                break;
            }
            //MyLog.i("iReceLenth= "+iReceLenth);
            for (int i=0;i<iReceLenth;i++ ) {
                //MyLog.i("i= "+i+ " Data="+receDataBuffer[i]);
                streamPort.ReceFrame(receDataBuffer[i]);
            }
        }
        MyLog.i(clientIpAddress+ " " + Thread.currentThread().getStackTrace()[2].getFileName() + "-->"
                + "Function: " + Thread.currentThread().getStackTrace()[2].getMethodName() + "-->"
                + "Line" + Thread.currentThread().getStackTrace()[2].getLineNumber() + ":\r\n"
        );
        Stop();
    }

    void LastTransProcess(byte[] DataBuffer, int iLength) {
        if (sendStream == null) return;
        if (socket == null) return;
        if (socket.isConnected() == false) return;
     //   MyLog.i("LastTransProcess()");
        try {
            sendStream.write(DataBuffer, 0, iLength);
            sendStream.flush();
        } catch (Exception e) {
            Stop();
            {
                //if (NeedExit() == false)
                    MyLog.i(Thread.currentThread().getStackTrace()[2].getFileName() + "-->"
                            + "Function: " + Thread.currentThread().getStackTrace()[2].getMethodName() + "-->"
                            + "Line" + Thread.currentThread().getStackTrace()[2].getLineNumber() + ":\r\n"
                            + "    Error:" + e.getMessage() + "\r\n\r\n"
                    );
            }
        }
    }

    public void LastReceProcess()
    {
        if (NeedExit()) return;
        if (clientManage==null) return;
        if (clientManage.clientsManage==null) return;
        if (clientManage.clientsManage.ledCardCommunication==null) return;

        Tick();
        switch (streamPort.ucCommandType)
        {
            case TICK:
                // Tick();
                break;
            case FPGA_MOONCELL:
                if (clientManage.clientsManage.ledCardCommunication.mooncellFpga==null) break;
                clientManage.clientsManage.ledCardCommunication.mooncellFpga.Operation(streamPort);
                break;

            case UART_SENSOR:
                //if (clientManage.clientsManage.ledCardCommunication.aidlSerialPort_Sensor==null) break;
                //clientManage.clientsManage.ledCardCommunication.aidlSerialPort_Sensor.// uart_Sensor.
                //    TransData_Byte(streamPort.ReceBuffer,streamPort.iReceLength);
                break;
            case UART_FPGA:
                if (clientManage.clientsManage.ledCardCommunication.mooncellFpga==null) break;

                synchronized (clientManage.clientsManage.ledCardCommunication.mooncellFpga.objFpgaReadOrWrite)
            {   byte[] DataBuffer = new byte[StreamPort.MAX_PACKET_SIZE + 256];
                int iOffset=0;
                int data=0;
                // VGA 状态寄存器。
                iOffset=0;

                for (int i =0;i<0x100;i++) DataBuffer[iOffset++]=(byte)0x00;
                //if (false)
                    clientManage.clientsManage.ledCardCommunication.mooncellFpga.
                            //modified by alahover 20190413 -start
                            //SpiOperator(false,(0x70<<16)+ (0x00<<8) + 0x00,DataBuffer,iOffset);
                            SpiOperator(false,(0x70<<16)+ (0x00<<8) + 0x00,DataBuffer,iOffset,true);
                             //modified by alahover 20190413 -end
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                }
                // 亮度使能。

                iOffset=0;
                //MyLog.i("-------fw 7");
                for (int i =0;i<0x04;i++) DataBuffer[iOffset++]=(byte)0xA5;
                //if (false)
                clientManage.clientsManage.ledCardCommunication.mooncellFpga.
                        //modified by alahover 20190413 -start
                        //SpiOperator(true,(0xA7<<16)+ (0x20<<8) + 0x0E*4,DataBuffer,iOffset);

                SpiOperator(true,(0xA7<<16)+ (0x20<<8) + 0x0E*4,DataBuffer,iOffset,false);
                //modified by alahover 20190413 -end
                //if (false)
                while (data<0x70000000)
                {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e1) {
                        e1.printStackTrace();
                    }
                    // 亮度调节。
                    iOffset=0;
                    int iValue = data << 20 | data << 10 | data;
                    DataBuffer[iOffset++] = (byte) (iValue >> 24);
                    DataBuffer[iOffset++] = (byte) (iValue >> 16);
                    DataBuffer[iOffset++] = (byte) (iValue >> 8);
                    DataBuffer[iOffset++] = (byte) (iValue >> 0);

                    clientManage.clientsManage.ledCardCommunication.mooncellFpga.
                    //modified by alahover 20190413 -start
                    //        SpiOperator(true,(0xA7<<16)+ (0x20<<8) + 0x0D*4,DataBuffer,iOffset);

                    SpiOperator(true,(0xA7<<16)+ (0x20<<8) + 0x0D*4,DataBuffer,iOffset,false);
                    //modified by alahover 20190413 -end
                 //   MyLog.i("-------fw 8");

                    data += 0x10;
                    if (data>=0x400) data=0;
                    MyLog.i("data= "+data);
                }

 /*
                    iOffset=0;

                    DataBuffer[iOffset++] = (byte) 0x7E;
                    DataBuffer[iOffset++] = (byte) 0x7E;
                    DataBuffer[iOffset++] = (byte) 0x55;
                    DataBuffer[iOffset++] = (byte) 0x7C;

                    DataBuffer[iOffset++] = (byte) 0x00;
                    DataBuffer[iOffset++] = (byte) 0x00;
                    DataBuffer[iOffset++] = (byte) 0x00;
                    DataBuffer[iOffset++] = (byte) 0x00;

                    DataBuffer[iOffset++] = (byte) 8+2;
                    DataBuffer[iOffset++] = (byte) 0x00+1;
                    DataBuffer[iOffset++] = (byte) 0x00;
                    DataBuffer[iOffset++] = (byte) 0x00;

                    DataBuffer[iOffset++] = (byte) 0x00;
                    DataBuffer[iOffset++] = (byte) 0x00;

                    DataBuffer[iOffset++]=(byte)0xAA;
                    DataBuffer[iOffset++]=(byte)0x70;
                    DataBuffer[iOffset++]=(byte)0x00;
                    DataBuffer[iOffset++]=(byte)0x00;
                    DataBuffer[iOffset++]=(byte)0x01;
                    DataBuffer[iOffset++]=(byte)0x00;
                    DataBuffer[iOffset++]=(byte)0x00;
                    DataBuffer[iOffset++]=(byte)0x00;

                    for (int i =0;i<0x100;i++) DataBuffer[iOffset++]=(byte)0x00;

                    DataBuffer[iOffset] = (byte) GetCheckCodeIn8(DataBuffer,3, iOffset); // 校验码。
                    iOffset++;

                    if (false)
                    {}//clientManage.clientsManage.ledCardCommunication.mooncellFpga.
                        //    TransData_Byte((byte)0,DataBuffer,iOffset);

*/
/*

                    DataBuffer[iOffset++] = (byte) 0x7E;
                    DataBuffer[iOffset++] = (byte) 0x7E;
                    DataBuffer[iOffset++] = (byte) 0x55;
                    DataBuffer[iOffset++] = (byte) 0x7C;

                    DataBuffer[iOffset++] = (byte) 0x00;
                    DataBuffer[iOffset++] = (byte) 0x00;
                    DataBuffer[iOffset++] = (byte) 0x00;
                    DataBuffer[iOffset++] = (byte) 0x00;

                    DataBuffer[iOffset++] = (byte) 12+2;
                    DataBuffer[iOffset++] = (byte) 0x00;
                    DataBuffer[iOffset++] = (byte) 0x00;
                    DataBuffer[iOffset++] = (byte) 0x00;

                    DataBuffer[iOffset++] = (byte) 0x00;
                    DataBuffer[iOffset++] = (byte) 0x00;


                    DataBuffer[iOffset++]=(byte)0xE5;

                    DataBuffer[iOffset++]=(byte)0xA7;
                    DataBuffer[iOffset++]=(byte)0x20;
                    DataBuffer[iOffset++]=(byte)0x0E *4;

                    DataBuffer[iOffset++]=(byte)0x00;
                    DataBuffer[iOffset++]=(byte)0x04;

                    DataBuffer[iOffset++]=(byte)0x00;
                    DataBuffer[iOffset++]=(byte)0x00;

                    for (int i =0;i<0x04;i++) DataBuffer[iOffset++]=(byte)0xA5;



                    DataBuffer[iOffset] = (byte) GetCheckCodeIn8(DataBuffer,3, iOffset); // 校验码。
                    iOffset++;

                    //if (false)
                    clientManage.clientsManage.ledCardCommunication.mooncellFpga.
                            TransData_Byte((byte)0,DataBuffer,iOffset);
*/

                    /*

                    // 回读亮度调节。
                    iOffset=0;
                    DataBuffer[iOffset++]=(byte)0xAA;

                    DataBuffer[iOffset++]=(byte)0xA7;
                    DataBuffer[iOffset++]=(byte)0x20;
                    DataBuffer[iOffset++]=(byte)0x0D*4;

                    DataBuffer[iOffset++]=(byte)0x00;
                    DataBuffer[iOffset++]=(byte)0x08;

                    DataBuffer[iOffset++]=(byte)0x00;
                    DataBuffer[iOffset++]=(byte)0x00;
                    for (int i =0;i<0x08;i++) DataBuffer[iOffset++]=0;
                        /*
                        DataBuffer[iOffset++] = (byte) 0x7E;
                        DataBuffer[iOffset++] = (byte) 0x7E;
                        DataBuffer[iOffset++] = (byte) 0x55;
                        DataBuffer[iOffset++] = (byte) 0x7C;

                        DataBuffer[iOffset++] = (byte) 0x00;
                        DataBuffer[iOffset++] = (byte) 0x00;
                        DataBuffer[iOffset++] = (byte) 0x00;
                        DataBuffer[iOffset++] = (byte) 0x00;

                        DataBuffer[iOffset++] = (byte) 12+2;
                        DataBuffer[iOffset++] = (byte) 0x00;
                        DataBuffer[iOffset++] = (byte) 0x00;
                        DataBuffer[iOffset++] = (byte) 0x00;

                        DataBuffer[iOffset++] = (byte) 0x00;
                        DataBuffer[iOffset++] = (byte) 0x00;




                        DataBuffer[iOffset++] = (byte) 0xE5;

                        DataBuffer[iOffset++] = (byte) 0xA7;
                        DataBuffer[iOffset++] = (byte) 0x20;
                        DataBuffer[iOffset++] = (byte) 0x0D * 4;

                        DataBuffer[iOffset++] = (byte) 0x00;
                        DataBuffer[iOffset++] = (byte) 0x04;

                        DataBuffer[iOffset++] = (byte) 0x00;
                        DataBuffer[iOffset++] = (byte) 0x00;


                        int iValue = data << 20 | data << 10 | data;
                        MyLog.i("Received Command3 iValue: " + iValue);
                        DataBuffer[iOffset++] = (byte) (iValue >> 24);
                        DataBuffer[iOffset++] = (byte) (iValue >> 16);
                        DataBuffer[iOffset++] = (byte) (iValue >> 8);
                        DataBuffer[iOffset++] = (byte) (iValue >> 0);

                        DataBuffer[iOffset] = (byte) GetCheckCodeIn8(DataBuffer,3, iOffset); // 校验码。

                        //MyLog.i("iOffset= "+iOffset);
                        //MyLog.i("DataBuffer[iOffset]= "+DataBuffer[iOffset]);

                        iOffset++;




                        MyLog.i("data= "+data);
                        //if (false)
                        clientManage.clientsManage.ledCardCommunication.mooncellFpga.
                                TransData_Byte((byte) 0, DataBuffer, iOffset);

                    if (false)
                    clientManage.clientsManage.ledCardCommunication.mooncellFpga.
                            TransData_Byte((byte)0,DataBuffer,iOffset);
                    // 写。
                    iOffset=0;
                    DataBuffer[iOffset++]=(byte)0xE5;

                    DataBuffer[iOffset++]=(byte)0xA7;
                    DataBuffer[iOffset++]=(byte)0x20;
                    DataBuffer[iOffset++]=(byte)0x00;

                    DataBuffer[iOffset++]=(byte)0x00;
                    DataBuffer[iOffset++]=(byte)0x08;

                    DataBuffer[iOffset++]=(byte)0x00;
                    DataBuffer[iOffset++]=(byte)0x00;
                    for (int i =0;i<0x08;i++) DataBuffer[iOffset++]=(byte) i;
                    clientManage.clientsManage.ledCardCommunication.mooncellFpga.
                                TransData_Byte((byte)0,DataBuffer,iOffset);
                    // 回读。
                    iOffset=0;
                    DataBuffer[iOffset++]=(byte)0xAA;

                    DataBuffer[iOffset++]=(byte)0xA7;
                    DataBuffer[iOffset++]=(byte)0x20;
                    DataBuffer[iOffset++]=(byte)0x00;

                    DataBuffer[iOffset++]=(byte)0x00;
                    DataBuffer[iOffset++]=(byte)0x08;

                    DataBuffer[iOffset++]=(byte)0x00;
                    DataBuffer[iOffset++]=(byte)0x00;
                    for (int i =0;i<0x08;i++) DataBuffer[iOffset++]=0;
                    clientManage.clientsManage.ledCardCommunication.mooncellFpga.
                                TransData_Byte((byte)0,DataBuffer,iOffset);
                                */
            }

            break;
            case UART_EXTENSION:
                if (clientManage.clientsManage.ledCardCommunication.aidlSerialPort_Extention==null) break;

                MyLog.i("Received Command: " + streamPort.ucCommandType);

            {   byte[] DataBuffer = new byte[StreamPort.MAX_PACKET_SIZE + 256];
                int iOffset=0;

                iOffset=0;
                DataBuffer[iOffset++] = (byte) 0x7E;
                DataBuffer[iOffset++] = (byte) 0x7E;
                DataBuffer[iOffset++] = (byte) 0x55;
                DataBuffer[iOffset++] = (byte) 0x71;

                Define.SetIntToByte(0, DataBuffer, iOffset);
                iOffset +=4;

                Define.SetIntToByte(streamPort.iReceLength+1+13, DataBuffer, iOffset);
                iOffset +=4;

                DataBuffer[iOffset++] = (byte) 1;

                {   DataBuffer[iOffset++] = (byte) 0x7E;
                    DataBuffer[iOffset++] = (byte) 0x7E;
                    DataBuffer[iOffset++] = (byte) 0x55;
                    int iOffsetStart=iOffset;
                    DataBuffer[iOffset++] = (byte) 0x31;
                    Define.SetIntToByte(0, DataBuffer, iOffset);
                    iOffset +=4;

                    Define.SetIntToByte(streamPort.iReceLength, DataBuffer, iOffset);
                    iOffset +=4;

                    if (streamPort.ReceBuffer!=null && streamPort.iReceLength>0) {
                        System.arraycopy(streamPort.ReceBuffer, 0, DataBuffer, iOffset, streamPort.iReceLength);        // 正文内容。
                        iOffset += streamPort.iReceLength;
                    }
                    DataBuffer[iOffset] = Define.GetCheckCodeIn8(DataBuffer, iOffsetStart, iOffset);  // 校验码，累加和取反。
                    iOffset++;
                }

                DataBuffer[iOffset] = Define.GetCheckCodeIn8(DataBuffer, 3, iOffset);  // 校验码，累加和取反。
                iOffset++;

                clientManage.clientsManage.ledCardCommunication.aidlSerialPort_Extention.
                        TransData_Byte(DataBuffer,iOffset);

                MyLog.i("Send Length= "+iOffset + "; streamPort.iReceLength="+ streamPort.iReceLength);
            }
            //clientManage.clientsManage.ledCardCommunication.aidlSerialPort_Extention.// uart_Extension.
            //    TransData_Byte(streamPort.ReceBuffer,streamPort.iReceLength);
            break;

        }
    }

    public void Stop()
    {
        //if (false)
        try {
            bReady=false;

            if (NeedExit()==false)  // 非外部请求造成的退出，需要注销当前显示屏。
                clientManage.Request_Exit();
        
            if (receStream!=null) receStream.close();
            receStream=null;
            if (sendStream!=null) sendStream.close();
            sendStream=null;
            if (socket!=null) socket.close();
            socket=null;

            clientManage=null;
        } catch (Exception e) {}
	    //if (NeedExit()==false)
		    MyLog.i(clientIpAddress+ " "+ Thread.currentThread().getStackTrace()[2].getFileName() + "-->"
				    +   "Function: " +Thread.currentThread().getStackTrace()[2].getMethodName()
		    );
    }


    String strDisplayID=null;
    public String GetDisplayID() {   return  strDisplayID;}

    boolean bReady=false;
    public  boolean GetReady() { return bReady; }

    boolean bNeedExit=false;
    boolean NeedExit() { return bNeedExit; }

    public void Exit()
    {    if (bNeedExit) return;
        bNeedExit=true;
        Stop();
    }
    
}