#include "fingerprint.h"

/*起始帧*/
#define GR_PACK_HEAD 0XEF01
/* 包标识*/
#define GR_PACK_COMMAND_FLAG 0X01
//当为2时，表示后续还有包
#define GR_PACK_DATA_FALG 0X02
#define GR_PACK_ACK_FALG 0X07
#define GR_PACK_END_FALG 0X08
// 包长度 = 数据到校验和之间的长度
// 校验和 = 包标识 ~ 校验和之间的和 ，超两个字节对高位进行忽略

Fingerprint::Fingerprint(Stream *UART, uint32_t ADDRRESS)
{
    _uart = UART;
    _addr = ADDRRESS;
    _headBuffer[0] = 0xEF;
    _headBuffer[1] = 0x01;
    memcpy(&_headBuffer[2], &_addr, sizeof(_addr));
};

Fingerprint::~Fingerprint(void)
{

};

/*********************
 *  0   1   2   3   4   5   6       7       8      9      10     11
 *  ef  01  ff  ff  ff  ff  flag   len_h    len_l  code   sum_h  sum_l
 * *******************/
bool Fingerprint::validSum(uint8_t *resp, uint8_t len)
{
    uint16_t sum = 0;
    for (int i = 6; i < len - 2; i++) {
        sum += resp[i];
    }
    // Serial.printf("sum:%x  -2:%x -1:%x \n", sum, resp[len - 2], resp[len - 1]);
    // Serial.printf("merge: %x \n", (resp[len - 2] << 8 | resp[len - 1]));
    return sum == (resp[len - 2] << 8 | resp[len - 1]);
}

bool Fingerprint::waitForAck(uint8_t *reqs, uint8_t len)
{
    uint32_t i = 0, timerStart = millis();
    while (1) {
        if (_uart->available()) {
            reqs[i++] = _uart->read();
            Serial.print(reqs[i - 1], HEX);
            Serial.print(" ");
            if (i >= len) {
                Serial.println();
                break;
            }
        }
        if (millis() - timerStart > 1000) {
            Serial.printf("time out\n");
            return false;
        }
    }
    return true;
}

int Fingerprint::waitForResp(uint8_t respSize, uint32_t timeout)
{
    int i = 0;
    uint32_t timerStart = millis();
    uint8_t response[respSize];
    while (1) {
        if (_uart->available()) {
            response[i++] = _uart->read();
            if (i >= sizeof(response))
                break;
        }
        if (millis() - timerStart > 1000 * timeout) {
            return -1;
        }
    }
    if (validSum(response, sizeof(response))) {
        return response[9];
    }
    return -1;
}

void Fingerprint::__sendCom(uint8_t command, uint16_t len)
{
    uint16_t sum = 0;
    uint8_t commandBuffer[6];
    commandBuffer[0] = GR_PACK_COMMAND_FLAG;
    commandBuffer[1] = (len & 0xFF00) >> 8;
    commandBuffer[2] = len & 0xFF;
    commandBuffer[3] = command;

    for (int i = 0; i < sizeof(commandBuffer) - 2; i++) {
        sum += commandBuffer[i];
    }
    commandBuffer[4] = (sum & 0xFF00) >> 8;
    commandBuffer[5] = sum & 0xFF;
    _uart->write(_headBuffer, sizeof(_headBuffer));
    _uart->write(commandBuffer, sizeof(commandBuffer));
}

/**
 * @brief  录入指纹到ImageBuffer
 * @note   标准应答格式 12Bytes
 * @retval 0H ~ 03H
 */
bool Fingerprint::entryFinger(void)
{
    int ret = GR_OK;

    __sendCom(GR_GET_IMAGE, 0x03);

    ret = waitForResp(12, 15);
    if (ret != GR_OK) {
        getErrorReason(ret);
    }
    return ret == GR_OK;
}

void Fingerprint::getErrorReason(int err)
{
    // Serial.printf("Error :[%d]\n", err);
    switch (err) {
    case 0:
        break;
    }
}

/**
 * @brief  生成特征标识
 * @note   标准应答格式 12Bytes
 * @param  id: 01H ~ 02H
 * @retval
 */
bool Fingerprint::generateFeature(GR_BufID_t id)
{
    int ret = GR_OK;
    uint8_t commandBuffer[7];
    _uart->write(_headBuffer, 6);
    commandBuffer[0] = GR_PACK_COMMAND_FLAG;
    commandBuffer[1] = 0x00;
    commandBuffer[2] = 0x04;
    commandBuffer[3] = GR_GET_CHAR;
    commandBuffer[4] = id;
    commandBuffer[5] = 0x00;
    commandBuffer[6] = 0x07 + id;
    _uart->write(commandBuffer, sizeof(commandBuffer));
    ret = waitForResp(12, 1);
    if (ret != GR_OK) {
        getErrorReason(ret);
    }
    return ret == GR_OK;
}

/**
 * @brief  精确比对两枚指纹特征
 * @note   //! 非标准应答格式 14Bytes
 * @retval 0x00  0x01 0x08
 */
bool Fingerprint::matchFingerprint(void)
{
    int ret = GR_OK;

    __sendCom(GR_MATCH, 0x03);
    ret = waitForResp(14, 1);
    if (ret != GR_OK) {
        getErrorReason(ret);
    }
    return ret == GR_OK;
}

/**
 * @brief  搜索指纹
 * @note   //! 非标准应答格式 16Bytes
 * @retval 确认字，页码（相配指纹模板）
 */
bool Fingerprint::searchFingerprint(GR_BufID_t id, uint16_t sPage, uint16_t pNum)
{
    int ret = GR_OK;
    uint32_t sum = 0;
    uint8_t commandBuffer[11];
    _uart->write(_headBuffer, 6);
    commandBuffer[0] = GR_PACK_COMMAND_FLAG;
    commandBuffer[1] = 0x00;
    commandBuffer[2] = 0x08;
    commandBuffer[3] = GR_SEARCH;
    commandBuffer[4] = id;
    commandBuffer[5] = (sPage & 0xFF00) >> 8;
    commandBuffer[6] = sPage & 0xFF;
    commandBuffer[7] = (pNum & 0xFF00) >> 8;
    commandBuffer[8] = pNum & 0xFF;

    for (int i = 0; i < sizeof(commandBuffer) - 2; i++) {
        sum += commandBuffer[i];
    }
    commandBuffer[9] = (sum & 0x00FF00) >> 8;
    commandBuffer[10] = sum & 0xFF;

    _uart->write(commandBuffer, sizeof(commandBuffer));
    ret = waitForResp(16, 1);
    if (ret != GR_OK) {
        getErrorReason(ret);
    }
    return ret == GR_OK;
}

/**
 * @brief  合并特征(生成模板)
 * @note   标准应答格式 12Bytes
 * @retval 0x00 0x01 0x0A
 */
bool Fingerprint::mergeFeature(void)
{
    int ret = GR_OK;
    uint8_t commandBuffer[6];
    _uart->write(_headBuffer, 6);
    commandBuffer[0] = GR_PACK_COMMAND_FLAG;
    commandBuffer[1] = 0x00;
    commandBuffer[2] = 0x03;
    commandBuffer[3] = GR_REG_MODEL;
    commandBuffer[4] = 0x00;
    commandBuffer[5] = 0x09;
    _uart->write(commandBuffer, sizeof(commandBuffer));
    ret = waitForResp(12, 1);
    if (ret != GR_OK) {
        getErrorReason(ret);
    }
    return ret == GR_OK;
}

/**
 * @brief  储存模板
 * @note   标准应答格式 12Bytes
 * @retval
 */
bool Fingerprint::storeFeature(GR_BufID_t id, uint16_t posNum)
{
    int ret = GR_OK;
    uint32_t sum = 0;
    uint8_t commandBuffer[9];
    _uart->write(_headBuffer, 6);
    commandBuffer[0] = GR_PACK_COMMAND_FLAG;
    commandBuffer[1] = 0x00;
    commandBuffer[2] = 0x06;
    commandBuffer[3] = GR_STORE_CHAR;
    commandBuffer[4] = id;
    commandBuffer[5] = (posNum & 0xFF00) >> 8;
    commandBuffer[6] = posNum & 0xFF;
    for (int i = 0; i < sizeof(commandBuffer) - 2; i++) {
        sum += commandBuffer[i];
    }
    commandBuffer[7] = (sum & 0x00FF00) >> 8;
    commandBuffer[8] = sum & 0xFF;

    _uart->write(commandBuffer, sizeof(commandBuffer));
    ret = waitForResp(12, 1);
    if (ret != GR_OK) {
        getErrorReason(ret);
    }
    return ret == GR_OK;
}

/**
 * @brief  读出模板
 * @note   标准应答格式 12Bytes,将flash数据库中指定ID号的指纹模板读入到模板缓冲区CharBuffer1或CharBuffer2
 * @retval
 */
bool Fingerprint::loadFeature(GR_BufID_t id, uint16_t pNum)
{
    int ret = GR_OK;
    uint32_t sum = 0;
    uint8_t commandBuffer[9];
    _uart->write(_headBuffer, 6);
    commandBuffer[0] = GR_PACK_COMMAND_FLAG;
    commandBuffer[1] = 0x00;
    commandBuffer[2] = 0x06;
    commandBuffer[3] = GR_LOAD_CHAR;
    commandBuffer[4] = id;
    commandBuffer[5] = (pNum & 0xFF00) >> 8;
    commandBuffer[6] = pNum & 0xFF;
    for (int i = 0; i < sizeof(commandBuffer) - 2; i++) {
        sum += commandBuffer[i];
    }
    commandBuffer[7] = (sum & 0x00FF00) >> 8;
    commandBuffer[8] = sum & 0xFF;

    _uart->write(commandBuffer, sizeof(commandBuffer));
    ret = waitForResp(12, 1);
    if (ret != GR_OK) {
        getErrorReason(ret);
    }
    return ret == GR_OK;
}

/**
 * @brief  上传特征或模板
 * @note   标准应答格式 12Bytes
 * @retval
 */
bool Fingerprint::uplaodFeature(GR_BufID_t id)
{
    int ret = GR_OK;
    uint32_t sum = 0;
    uint8_t commandBuffer[7];
    _uart->write(_headBuffer, 6);
    commandBuffer[0] = GR_PACK_COMMAND_FLAG;
    commandBuffer[1] = 0x00;
    commandBuffer[2] = 0x04;
    commandBuffer[3] = GR_UP_CHAR;
    commandBuffer[4] = id;
    for (int i = 0; i < sizeof(commandBuffer) - 2; i++) {
        sum += commandBuffer[i];
    }
    commandBuffer[5] = (sum & 0x00FF00) >> 8;
    commandBuffer[6] = sum & 0xFF;

    _uart->write(commandBuffer, sizeof(commandBuffer));
    ret = waitForResp(12, 1);
    if (ret != GR_OK) {
        getErrorReason(ret);
    }
    return ret == GR_OK;
}

/**
 * @brief  下载特征或模板
 * @note   标准应答格式 12Bytes
 * @retval
 */
bool Fingerprint::downloadFeature(GR_BufID_t id)
{
    return true;
}

// /**
//  * @brief  上传原始图像
//  * @note   标准应答格式 12Bytes
//  * @retval
//  */
// bool Fingerprint::uploadImage(void)
// {
// }

// /**
//  * @brief  下载原始图像
//  * @note   标准应答格式 12Bytes
//  * @retval
//  */
// bool Fingerprint::downloadImage(void)
// {
// }

// /**
//  * @brief  删除模板
//  * @note   标准应答格式 12Bytes
//  * @retval
//  */
// bool Fingerprint::uploadImage(void)
// {
// }

// /**
//  * @brief  清空指纹库
//  * @note   标准应答格式 12Bytes
//  * @retval
//  */
// bool Fingerprint::deleteLibarry(void)
// {
// }

// /**
//  * @brief  写系统寄存器
//  * @note   标准应答格式 12Bytes
//  * @retval
//  */
// bool Fingerprint::writeSysReg(void)
// {
// }

/**
 * @brief  读系统基本参数
 * @note   //! 非标准应答格式 28Bytes
 * @retval
 */
bool Fingerprint::readSysParams(SysParams_t *params)
{
    uint8_t response[28];
    const uint8_t order[] = {0x01, 0x00, 0x03, 0x0F, 0x00, 0x13};
    _uart->write(_headBuffer, sizeof(_headBuffer));
    _uart->write(order, sizeof(order));
    if (waitForAck(response, sizeof(response))) {
        if (validSum(response, sizeof(response)) && response[9] == GR_OK) {
            Serial.printf("\nvalid pass\n\n");
            params->statusReg = (response[10] << 8) | response[11];
            params->code = response[12] << 8 | response[13];
            params->libSize = response[14] << 8 | response[15];
            params->level = response[16] << 8 | response[17];
            params->address = response[18] << 24 | response[19] << 16 | response[20] << 8 | response[21];
            params->packSize = response[22] << 8 | response[23];
            params->bps = response[24] << 8 | response[25];
            return true;
        }
    }
    return false;
}


bool Fingerprint::readINFpage()
{
    uint8_t response[255];
    const uint8_t order[] = {0x01, 0x00, 0x03, 0x16, 0x00, 0x19};
    _uart->write(_headBuffer, sizeof(_headBuffer));
    _uart->write(order, sizeof(order));
    if (waitForAck(response, sizeof(response))) {
        if (validSum(response, sizeof(response)) && response[9] == GR_OK) {
            Serial.printf("\nvalid pass\n\n");
            return true;
        }
    }
    return false;

}



// /**
//  * @brief  设置口令
//  * @note   //! 非标准应答格式 11Bytes
//  * @retval
//  */
// bool Fingerprint::setPassWord(void)
// {
// }

// /**
//  * @brief  验证口令
//  * @note   标准应答格式 12Bytes
//  * @retval
//  */
// bool Fingerprint::setPassWord(void)
// {
// }

// /**
//  * @brief  采样随机数
//  * @note   //! 非标准应答格式 16Bytes
//  * @retval
//  */
// bool Fingerprint::getRandom(void)
// {
// }

// /**
//  * @brief  设置模块地址
//  * @note   标准应答格式 12Bytes
//  * @retval
//  */
// bool Fingerprint::setAddress(void)
// {
// }

// /**
//  * @brief  端口控制
//  * @note   标准应答格式 12Bytes
//  * @retval
//  */
// bool Fingerprint::setAddress(void)
// {
// }

// /**
//  * @brief  写记事本
//  * @note   标准应答格式 12Bytes
//  * @retval
//  */
// bool Fingerprint::writeNotepad(void)
// {
// }

// /**
//  * @brief  读记事本
//  * @note   //! 非标准应答格式 44Bytes
//  * @retval
//  */
// bool Fingerprint::readNotepad(void)
// {
// }

// /**
//  * @brief  生成细化指纹图像
//  * @note   标准应答格式 12Bytes
//  * @retval
//  */
// bool Fingerprint::generateBinImage(void)
// {
// }

// /**
//  * @brief  读有效模板个数
//  * @note   //! 标准应答格式 14Bytes
//  * @retval
//  */
// bool Fingerprint::generateBinImage(void)
// {
// }

// /**
//  * @brief  读索引表
//  * @note   //! 非标准应答格式 44Bytes
//  * @retval
//  */
// bool Fingerprint::readNotepad(void)
// {
// }