package com.xixun.communicate.Protocol;

import com.xixun.communicate.Define;
import com.xixun.communicate.IFunctionCallBack;

import java.util.Arrays;

/**
 * Created by Administrator on 2018/01/17.
 */

public class StreamPort {
    public static byte STREAM_SYNC_HEAD = (0x7E);
    public static byte STREAM_SYNC_HEAD2 = (0x55);
    public static int MAX_PACKET_SIZE = (Define.FLASH_PAGE_SIZE * 4);//Define.FLASH_SIZE);
    public int iReceLength = 0;

    byte ucCheckCode = 0;
    int iReceCounter = 0;
    boolean bCheck = true;

    public NET_COMMU_TYPE ucCommandType = NET_COMMU_TYPE.NONE;
    public byte ucIdence = 0;
    public byte ucPipeId = 0;
    //added by alahover 20190412  -start
    public boolean m_bAck = false;
    //added by alahover 20190412 -end

    public byte[] ReceBuffer = new byte[MAX_PACKET_SIZE + 256];
    FRAME_PROTCAL_STAGE frameProtocalStage = FRAME_PROTCAL_STAGE.HEAD;

    public String clientIpAddress = null;

    IFunctionCallBack FunctionCallBack = null;

    public StreamPort() {
    }

    public StreamPort(String clientIpAddress, boolean bCheck, IFunctionCallBack FunctionCallBack) {
        this.clientIpAddress = clientIpAddress;
        this.bCheck = bCheck;
        this.FunctionCallBack = FunctionCallBack;
    }

    public boolean ReceFrame(byte ucReceData) {
        //System.out.println("ReceFrame "+" Data: "+ ucReceData);
        ReceBuffer[iReceCounter++] = ucReceData;
        ReceBuffer[iReceCounter] = 0; // 补零，用作字符串结束符。

        //System.out.println("frameProtocalStage= "+frameProtocalStage  + " Data: "+ ucReceData);

        switch (frameProtocalStage) {
            case HEAD:
                if (ReceHead(ucReceData)) frameProtocalStage = FRAME_PROTCAL_STAGE.NAMEPALAT;
                break;
            case NAMEPALAT:
                if (ReceNamepalat(ucReceData))
                    frameProtocalStage = (iReceLength > 0) ? FRAME_PROTCAL_STAGE.TEXT : FRAME_PROTCAL_STAGE.CHECK;
                break;
            case TEXT:
                if (ReceText(ucReceData)) frameProtocalStage = FRAME_PROTCAL_STAGE.CHECK;
                break;
            case CHECK:
                if (ReceCheck(ucReceData)) {
                    //System.out.println("ReceFrame Step 00 ucCommandType="+ucCommandType);
                    if (FunctionCallBack != null) {
                        FunctionCallBack.LastReceDataProcess(null, 0);
                    }
                    return true;
                }
                ReceClear();
                break;
            default:
                ReceClear();
                break;
        }
        return false;
    }

    Boolean ReceHead(byte ucReceData) {
        switch (iReceCounter) {
            case 1:
            case 2:
                //System.out.println("12 STREAM_SYNC_HEAD= "+STREAM_SYNC_HEAD  + " Data: "+ ucReceData);
                if (ucReceData != STREAM_SYNC_HEAD) {
                    if (ucReceData != STREAM_SYNC_HEAD2) ReceClear();
                    else {
                        if (iReceCounter == 2) iReceCounter = 3; // 第一个“STREAM_SYNC_HEAD”可能丢失，补上一个。
                        else ReceClear();
                    }
                }
                break;
            case 3:
                //System.out.println("3 frameProtocalStage= "+frameProtocalStage  + " Data: "+ ucReceData);
                if (ucReceData != STREAM_SYNC_HEAD2) ReceClear();
                break;
            case 4:
                //System.out.println("4 frameProtocalStage= "+frameProtocalStage  + " Data: "+ ucReceData);
                ReceClear();
                ucCheckCode = ucReceData; // 命令类型开始计数。
                ucIdence = 0;
                ucPipeId = 0;
                ucCommandType = NET_COMMU_TYPE.GetEnumValue(ucReceData);
                //System.out.println("ReceHead Received Command: " + ucCommandType);
                return true;
            default:
                ReceClear();
                break;
        }
        return false;
    }

    Boolean ReceNamepalat(byte ucReceData) {
        ucCheckCode += ucReceData;

        switch (iReceCounter) {
            case 1:
                ucIdence = ucReceData;
                break;
            case 2:
                ucPipeId = ucReceData;
                break;
            //20190412 added by alahover -start
            case 3:
                if (ucReceData == 1)
                    m_bAck = true;
                else
                    m_bAck = false;
                break;
            //20190412 added by alahover -end
            case 8:
                iReceLength = Define.GetIntFromByte(ReceBuffer, 4);
                ReceClear();
                //System.out.println("-----------------Received Command Length: " + iReceLength);
                if (iReceLength <= ReceBuffer.length) return true;
                break;
        }
        return false;
    }

    Boolean ReceText(byte ucReceData) {
        ucCheckCode += ucReceData;
        return (iReceCounter == iReceLength);
    }

    Boolean ReceCheck(byte ucReceData) {
        if (ucCheckCode == ~ucReceData) {
            ReceBuffer[iReceCounter] = '\0'; // 补零，防止字符串。
            return true;
        } else {
            //System.out.println("iReceLength="+iReceLength+ ", Need CheckCode: " + "0x" + Integer.toHexString((~ucCheckCode)& 0xFF) + ", Error Received: " + "0x" + Integer.toHexString(ucReceData& 0xFF));
        }
        if (bCheck == false) return true;

        return false;
    }


    void ReceClear() {
        frameProtocalStage = FRAME_PROTCAL_STAGE.HEAD;
        iReceCounter = 0;
    }

    public void TransData_Byte(byte ucCommand, byte ucIdence, byte ucPipeId, byte[] DataBuffer, int iLength) {
        int iOffset = 0;
        //System.out.println("1 Trans Command: "+ucCommand);

        byte[] dataBuffer = new byte[iLength + 13];

        dataBuffer[iOffset++] = STREAM_SYNC_HEAD;                       // 0x7E，同步头。
        dataBuffer[iOffset++] = STREAM_SYNC_HEAD;                       // 0x7E。
        dataBuffer[iOffset++] = STREAM_SYNC_HEAD2;                      // 0x55。
        dataBuffer[iOffset++] = ucCommand;

        dataBuffer[iOffset++] = ucIdence;                               // 分组号。
        dataBuffer[iOffset++] = ucPipeId;                               // 应答管道号。
        dataBuffer[iOffset++] = 0;                                      // 保留字。
        dataBuffer[iOffset++] = 0;                                      // 保留字。

        Define.SetIntToByte(iLength, dataBuffer, iOffset);                  // 正文长度。
        iOffset += 4;

        if (DataBuffer != null && iLength > 0) {
            System.arraycopy(DataBuffer, 0, dataBuffer, iOffset, iLength);        // 正文内容。
            iOffset += iLength;
        }

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

        if (FunctionCallBack != null) {
            FunctionCallBack.LastSendDataProcess(dataBuffer, iOffset);
          //  System.out.println("---------LastSendDataProcess ok iOffset="+iOffset);
        }
    }


    /**
     * 功能：从spi读取发送接收卡参数，保存成文件
     */
    public int GetFpgaParamFileFromSpi(String strFileName) {


        return 0;
    }

    @Override
    public String toString() {
        return "StreamPort{" +
                "iReceLength=" + iReceLength +
                ", ucCheckCode=" + ucCheckCode +
                ", iReceCounter=" + iReceCounter +
                ", bCheck=" + bCheck +
                ", ucCommandType=" + ucCommandType +
                ", ucIdence=" + ucIdence +
                ", ucPipeId=" + ucPipeId +
                ", m_bAck=" + m_bAck +
                ", ReceBuffer=" + Arrays.toString(ReceBuffer) +
                ", frameProtocalStage=" + frameProtocalStage +
                ", clientIpAddress='" + clientIpAddress + '\'' +
                ", FunctionCallBack=" + FunctionCallBack +
                '}';
    }
}

/**
  *
 */
