package com.tsi.comm.server.protocol;

/**
 * CVIB protocol
 */
public final class TsiCvibProtocolSpec {
    /*
    // 헤더(10), 상태헤더(8), 상태정보(5)*상태정보건수, 체크섬(2)
    // CVIB Protocol Format(CPU-->CENTER)
    //TYPE    STX1    STX2    LEN                OPCODE  DataVer NodeID  DATA    CHKSUM
    //Size    Byte    Byte    2Byte              Byte    1Byte   4Byte   NByte   2Byte
    //Value   0x7E    0x7E    Size(LEN…CHKSUM)   0x13    0x01            …     CRC16
    //- LEN   : LEN∼CHKSUM data length
    //        - OPCODE: 0x13, 신호상태정보전송
    //        - NodeID: Node ID
    //- DATA  : Opcode에 따른 데이터 영역
    //- CRC16 : CCITT / ITU / CRC - 16, bits shift right, final little(x) big(o) endian encoding.from LEN to DATA

    // 10 byte
    uint8_t         stx1;                   // stx 0x7E
    uint8_t         stx2;                   // stx 0x7E
    uint8_t         length[2];              // length, length byte ~ check sum
    uint8_t         opcode;                 // op code, 0x13
    uint8_t         dataVer;                // Data Version
    uint8_t         nodeid[4];              // signal node id
    // 8 byte
    tsc_cvim_hdr_t  hdr;                    // 8 byte, cvim signal status header
    // 5 byte * count
    tsc_cvim_stts_t stts[MAX_CVIM_STTS];    // 5 byte * 127 = 635 byte

    // cvim-raw packet header
#define TIMESPEC_SIZE       (sizeof(struct timespec))   // 16 bytes
    uint8_t pktTm[TIMESPEC_SIZE]; // little endian
    uint8_t ipaddr[4];  // big endian
    uint8_t port[2];    // big endian
    uint8_t connect;
    uint8_t nodeid[4];  // big endian

typedef struct _tsc_cvim_hdr_s
{
    uint8_t manual      : 1;    // 수동, 1: 이상, 0: 정상
    uint8_t blink       : 1;    // 점멸, 1: 점멸, 0: 정상
    uint8_t turnOff     : 1;    // 소등, 1: 소등, 0: 정상
    uint8_t response    : 1;    // 감응, 1: 감응, 0: 정상
    uint8_t trans       : 1;    // 전이, 1: 전이중, 0: 전이완료
    uint8_t byte1Res0   : 3;    // 예약, bit 7 ~ 5

    uint8_t conflict    : 1;    // 모순 이상, 1 : 이상, 0 : 정상
    uint8_t centerComm  : 1;    // 센터 통신 이상, 1: 센터 통신이상, 0 : 정상
    uint8_t scuComm     : 1;    // SCU 통신 이상,  1: MCU <--> SCU 통신 이상, 0: 정상
    uint8_t byte2Res0   : 5;    // 예약, bit 7 ~ 3

    uint8_t cycleCounter;       // 주기 카운터, 초

    uint8_t sttsCount   : 7;    // 총 신호상태정보의 개수, N 개
    uint8_t splitFlag   : 1;    // 데이터를 분할하여 전송할 경우 마지막 정보임을 나타내는 플래그(분할 패킷의 처음과 중간:0, 단일 또는 마지막 패킷:1)

    uint8_t currTime[4];        // 현재시간, time_t형, Big Endian
} tsc_cvim_hdr_t, *ptsc_cvim_hdr_t;

typedef struct _tsc_cvim_stts_s
{
    uint8_t dirAdd      : 4;    // 3 ~ 0, 방향추가정보, 해당 방향에 연등지 없음(0), 해당 방향의 첫번째 연등지(1), 해당 방향의 두번째 연등지(2)
    uint8_t lightInfo   : 4;    // 7 ~ 4, 신호등 정보, ■ 미지정(0), 직진(1), 좌회전(2), 보행자(3), 자전거(4), 우회전(5), 버스(6), 유턴(7)

    uint8_t lighting    : 3;    // 2 ~ 0, 신호등 상태, ■ 소등(0), 적색점등(1), 황색점등(2), 녹색점등(3), 적색점멸(4), 황색점멸(5), 녹색점멸(6)
    uint8_t unprotect   : 1;    // 3, 비보호 상태, ■ 신호등 정보 유턴/좌회전에 대한 비보호 여부, ■ 비보호 아님(0), 비보호(1)
    uint8_t Reserved0   : 2;    // 5 ~ 4, 예비, ■ 예비
    uint8_t walkerPush  : 1;    // 6, 보행자(푸쉬 또는 자동검지), ■ 없음(0), 버튼 눌림 or 자동검지(1)
    uint8_t timeFlag    : 1;    // 7, 시간 정보 신뢰성, ■ 고정신호시간(0), 가변신호시간(1)

    uint8_t displayTm;          // 표출 시간, ■ 초
    uint8_t remainTm;           // 잔여 시간, ■ 초
    uint8_t dirCode;            // 방향 코드, ■ 출력지정 테이블에 지정된 방향코드
} tsc_cvim_stts_t, *ptsc_cvim_stts_t;
    */

    // TODO: 20240722 Protocol R28 Added
    public static final byte PROTOCOL_R27 = 0x01;
    public static final byte PROTOCOL_R28 = 0x1C;   // 28

    public static final byte STX1 = 0x7E;
    public static final byte STX2 = 0x7E;

    public static final int SIZE_HEAD         = 10;
    public static final int SIZE_STX1         = 1;
    public static final int SIZE_STX2         = 1;
    public static final int SIZE_LENGTH       = 2;
    public static final int SIZE_OPCODE       = 1;
    public static final int SIZE_VERSION      = 1;
    public static final int SIZE_NODE_ID      = 4;
    public static final int SIZE_STATUS_HDR   = 8;
    public static final int SIZE_STATUS_DATA  = 5;
    public static final int SIZE_CHECKSUM     = 2;
    public static final int SIZE_PACKET_DATA  = 18; // length, opcode, version, node_id, status_hdr, checksum

    public static final int INDEX_STX1        = 0;  // 0
    public static final int INDEX_STX2        = 1;  // 1
    public static final int INDEX_LENGTH      = 2;  // 2,3
    public static final int INDEX_OPCODE      = 4;  // 4
    public static final int INDEX_VERSION     = 5;  // 5
    public static final int INDEX_NODE_ID     = 6;  // 6,7,8,9
    public static final int INDEX_STATUS_HDR  = 10; // 10,11,12,13,14,15,16,17
    public static final int INDEX_STATUS_DATA = 18; // 18,19,20,21,22
    public static final int INDEX_STATUS_DIR_ADD = 0;       // 상태정보내 방향 추가 정보 인덱스
    public static final int INDEX_STATUS_DIRECTION = 4;     // 상태정보내 방향코드

    public static final int SIZE_NODE_DUMMY   = 1+1+2+1+1+2;    // stx1, stx1, length(2), opcode, version, checksum(2)
    public static final int SIZE_NODE_HEAD = SIZE_NODE_ID + SIZE_STATUS_HDR;
    public static final int POS_NODE_HEAD_NODEID = 0;       // node(4),
    public static final int POS_NODE_HEAD_COUNT = 7;        // node(4),

    public static final int SIZE_IPC_SIZE = 27;
    public static final int SIZE_TIMESPEC = 16;
    public static final int POS_IPC_TIMESPEC = 0;
    public static final int POS_IPC_IPADDR = 16;
    public static final int POS_IPC_PORT = 20;
    public static final int POS_IPC_CONNECT = 22;
    public static final int POS_IPC_NODEID = 23;
    public static final int POS_IPC_PACKET = SIZE_IPC_SIZE;
    public static final byte CONNECT = 0x01;
    public static final byte DISCONNECT = 0x00;

    // FOR Netty LengthFieldBasedFrameDecoder
    public static final int MAX_FRAME_LENGTH = 2048;
    public static final int LENGTH_FIELD_OFFSET = 2; // 길이 필드가 2번 인덱스에서 시작
    public static final int LENGTH_FIELD_LENGTH = 2; // 길이 필드의 크기는 2바이트
    public static final int LENGTH_ADJUSTMENT = -2; // 길이 필드 값에 더해야 할 조정값 (길이 필드 자체의 크기를 빼줌)
    public static final int INITIAL_BYTES_TO_STRIP = 0; // 프레임에서 제거할 초기 바이트 수

}
