#include "IS11Comon.h"
#ifdef _WIN32
#include <windows.h>
void delay(int ms){
    Sleep(ms);
}

#else
#include <unistd.h> // For usleep

void delay(int ms){
    usleep(ms * 1000); // Convert milliseconds to microseconds
}
#include <unistd.h>
#include <cstring>
#endif



u_char BufferForRead[10000];
int TotalIndexNow = 0;
u_char BufferFortempWrite[1000];
// MySerialWrite=nullptr;
SERIALWRITE MySerialWrite = nullptr;
SERIALREAD MySerialRead = nullptr;
bool isIS3Init = false;
uint16_t crc16(const uint8_t *data, size_t len, uint16_t polynomial)
{
    uint16_t i, j, tmp, CRC16;

    CRC16 = 0xFFFF; // CRC寄存器初始值
    for (i = 0; i < len; i++)
    {
        CRC16 ^= data[i];
        for (j = 0; j < 8; j++)
        {
            tmp = (uint16_t)(CRC16 & 0x0001);
            CRC16 >>= 1;
            if (tmp == 1)
            {
                CRC16 ^= polynomial; // 异或多项式
            }
        }
    }
    return CRC16;
}

size_t SendSettingCommand(u_char *Command, size_t CommandLenth, u_char *Value, size_t ValueLenth)
{
    memcpy(BufferFortempWrite, Command, CommandLenth);
    memcpy(BufferFortempWrite + CommandLenth, Value, ValueLenth);
    uint16_t crc = crc16(BufferFortempWrite, CommandLenth + ValueLenth);
    memcpy(BufferFortempWrite + CommandLenth + ValueLenth, &crc, 2);
    SerialWrite(BufferFortempWrite, CommandLenth + ValueLenth + 2);
    //  Serial.write(BufferFortempWrite, CommandLenth+ValueLenth + 2);
    return GetSetBackFromSensor();
}

size_t SendGetData(int shutter)
{
    int lenth = sizeof(GET_ALL_DN);
    uint16_t crc = crc16(GET_ALL_DN, lenth);
    memcpy(BufferFortempWrite, GET_ALL_DN, lenth);
    memcpy(BufferFortempWrite + lenth, &crc, 2);
    SerialWrite(BufferFortempWrite, lenth + 2);
    // Serial.write(BufferFortempWrite, lenth + 2);
    // Serial.println(shutter);


    delay(shutter);
    return GetInfoBackFromSensor(true);
}

size_t SendGetSensorInfo(u_char *Command, size_t lenth)
{

    uint16_t crc = crc16(Command, lenth);
    memcpy(BufferFortempWrite, Command, lenth);
    memcpy(BufferFortempWrite + lenth, &crc, 2);
    // Serial.println((int)MySerialWrite);
    //   Serial.write(BufferFortempWrite,lenth+2);
       //delay(200);
    SerialWrite(BufferFortempWrite, lenth + 2);

    size_t retunnumber = GetInfoBackFromSensor();

    return retunnumber;
}

size_t GetSetBackFromSensor()
{
    TotalIndexNow = 0;
    TotalIndexNow += (int)SerailRead(BufferForRead + TotalIndexNow, 1);

    while (TotalIndexNow < 8)
    {
        // Serial.println(TotalIndexNow);
        // Serial.write(BufferForRead,1);
        TotalIndexNow += (int)SerailRead(BufferForRead + TotalIndexNow, 1);
    }
    return TotalIndexNow;
}

bool panduanHeader()
{
    if (TotalIndexNow < 2)
    {
        return false;
        /* code */
    }
    int temp = 0;
    while (BufferForRead[temp] != 0x01 &&
           !(BufferForRead[temp + 1] == 0x03 || BufferForRead[temp + 1] == 0x06 || BufferForRead[temp + 1] == 0x10))
    {
        if (temp >= TotalIndexNow - 2)
        {
            break;
            /* code */
        }
        temp++;

        /* code */
    }
    memcpy(BufferForRead, BufferForRead + temp, TotalIndexNow - temp);
    TotalIndexNow = TotalIndexNow - temp;
    temp = 0;
    if (BufferForRead[temp] != 0x01 &&
        !(BufferForRead[temp + 1] == 0x03 || BufferForRead[temp + 1] == 0x06 || BufferForRead[temp + 1] == 0x10))
    {
        return false;
    }
    return true;
}

size_t GetInfoBackFromSensor(bool isbig) // big 是指用几个字节表示数据长度 暂时只发现采集数据时用两个字节
{

    if (isbig)
    {
        // 长度用两个字节表示
        //  Serial.println(shutter);
        // Serial.println("i am here12312312312312312");
        TotalIndexNow = 0;
        BufferForRead[0] = 0x00;
        TotalIndexNow +=(int) SerailRead(BufferForRead + TotalIndexNow, 2);

        // while(BufferForRead)

        while (!panduanHeader())
        {
            TotalIndexNow +=(int) SerailRead(BufferForRead + TotalIndexNow, 1);
        }
        while (TotalIndexNow < 4)
        {
            // Serial.write(BufferForRead,TotalIndexNow);
             //delay(20);
            // Serial.println("i am here12312312312312312");
            TotalIndexNow += (int)SerailRead(BufferForRead + TotalIndexNow, 1);
        }

        int lenth = BufferForRead[2] * 256 + BufferForRead[3];
        while (TotalIndexNow < lenth + 4)
        {
            // delay(20);
            // Serial.write(BufferForRead,TotalIndexNow);
            // Serial.println(lenth);
            //  Serial.println(TotalIndexNow);
            // Serial.println("i am here12312312312312312");
            TotalIndexNow +=(int) SerailRead(BufferForRead + TotalIndexNow, 1024);
        }
        return TotalIndexNow;
    }
    else
    {
        // 长度用一个字节表示
        TotalIndexNow = 0;
        TotalIndexNow += (int)SerailRead(BufferForRead + TotalIndexNow, 1);

        while (TotalIndexNow < 3)
        {
            TotalIndexNow += (int)SerailRead(BufferForRead + TotalIndexNow, 1);
        }
        int lenth = BufferForRead[2];
        while (TotalIndexNow < lenth + 5)
        {
            TotalIndexNow += (int)SerailRead(BufferForRead + TotalIndexNow, 1);
        }
        // Serial.write(BufferForRead,TotalIndexNow);
        return TotalIndexNow;
    }
}

size_t SerialWrite(u_char *data, size_t lenth)
{
    if (MySerialWrite != nullptr)
    {
        // Serial.println("init ok");
        return MySerialWrite(data, lenth);
    }

    return 0;
}

size_t SerailRead(u_char *data, size_t lenth)
{
    if (MySerialRead != nullptr)
    {
        return MySerialRead(data, lenth);
    }
    return 0;
}

void InitFunction(SERIALWRITE a, SERIALWRITE readfunc)
{
    MySerialWrite = a;
    MySerialRead = readfunc;
    //std::string temp = "01";
    //a((u_char *)temp.c_str(), 2);
    isIS3Init = true;
}

u_char *GetDataBufferPTR()
{
    return BufferForRead;
}
bool isSensorInit()
{
    return isIS3Init;
}

void CoverLittleAndBig(char *data, int lenth)
{
   char *tempdata = new char[lenth];
   memcpy(tempdata, data, lenth);

   for (size_t i = 0; i < lenth / 2; i++)
   {
       data[2 * i] = tempdata[2 * i + 1];
       data[2 * i + 1] = tempdata[2 * i];
       /* code */
   }
   delete[] tempdata;
}