// 秒寻科技
// 文件读写
// 周涛
// 2023-03-15

#include "../includes/includes.h"

// 从wav文件读取数据并放入指定内存地址
// file_name:文件名（绝对路径）
// times:当前读取次数，从0开始，依次累加
// data_length:每次读取的数据长度
// pdwOutData:输出数据
uint8 util_read_data_from_wav_file(char *file_name, int times, int data_length, int16 *pwOutData)
{
    if (pwOutData == NULL || data_length == 0)
    {
        return RET_FAIL;
    }

    int i = 0;
    char str_real[4] = {0};
    int data_real = 0;
    uint8 byFlag = 0;

    // 打开文件
    FILE *fp = fopen(file_name, "rb");
    if (!fp)
    {
        printf("can't open file %s %d\n", file_name, __LINE__);
        return RET_FAIL;
    }

    // 移动文件头指针到偏移处
    byFlag = fseek(fp, 44 + times * 2 * data_length, SEEK_SET); // wav文件前44个字节是文件头，数据从第45个字节开始
    if (byFlag != RET_OK)
    {
        return byFlag;
    }

    // 读取文件
    i = 0;
    while (!feof(fp))
    {
        memset(str_real, 0, sizeof(str_real));
        fread(str_real, 1, 2, fp); // 从当前文件指针处每次读一个字节，一共读出两个字节

        data_real = (int16)((str_real[0] & 0xff) | ((str_real[1] & 0xff) << 8));
        pwOutData[i] = data_real;

        i++;
        if (i >= data_length)
        {
            break;
        }
    }

    fclose(fp);

    return RET_OK;
}

// 从录音文件读取实数数据并放入指定内存地址
int util_read_real_number_from_audio_file(char *file_name, int offset, int data_length, float *data_real_ptr)
{
    if (data_real_ptr == NULL || data_length == 0)
    {
        return 0;
    }

    int i = 0;
    char str_real[8];
    short data_real;

    FILE *fp = fopen(file_name, "rb");
    if (!fp)
    {
        printf("can't open file %s %d\n", file_name, __LINE__);
        return 0;
    }

    fseek(fp, offset * 2, SEEK_SET);

    i = 0;
    while (!feof(fp))
    {
        memset(str_real, 0, sizeof(str_real));
        fread(str_real, 1, 2, fp);

        data_real = (short)((str_real[0] & 0xff) | ((str_real[1] & 0xff) << 8));
        data_real_ptr[i] = (float)data_real;

        // if (i < 100) {
        //     printf("%d %d %.8f\n", i, data_real, data_real_ptr[i]);
        // }

        i++;
        if (i >= data_length)
        {
            break;
        }
    }

    fclose(fp);

    return 1;
}

// 从文本文件读取实数数据并放入指定内存地址
int util_read_real_number_from_txt_file(char *file_name, int offset, int data_length, float *data_real_ptr)
{
    if (data_real_ptr == NULL || data_length == 0)
    {
        return 0;
    }

    int i = 0;
    char str_real[64];
    float data_real;

    FILE *fp = fopen(file_name, "r");
    if (!fp)
    {
        printf("can't open file %s %d\n", file_name, __LINE__);
        return 0;
    }

    i = 0;
    while (!feof(fp))
    {
        fscanf(fp, "%s", str_real);

        if (i < offset)
        {
            i++;
            continue;
        }

        data_real = atof(str_real);
        data_real_ptr[i - offset] = data_real;

        i++;
        if (i >= offset + data_length)
        {
            break;
        }

        // printf("%s %.8f\n", str_real, data_real);
    }

    fclose(fp);

    return 1;
}

// 从文本文件读取整数数据并放入指定内存地址
int util_read_int_number_from_txt_file(char *file_name, int offset, int data_length, int *data_int_ptr)
{
    if (data_int_ptr == NULL || data_length == 0)
    {
        return 0;
    }

    int i = 0;
    char str_real[64];
    int data_int;

    FILE *fp = fopen(file_name, "r");
    if (!fp)
    {
        printf("can't open file %s %d\n", file_name, __LINE__);
        return 0;
    }

    i = 0;
    while (!feof(fp))
    {
        fscanf(fp, "%s", str_real);

        if (i < offset)
        {
            i++;
            continue;
        }

        data_int = atoi(str_real);
        data_int_ptr[i - offset] = data_int;

        i++;
        if (i >= offset + data_length)
        {
            break;
        }

        // printf("%s %.8f\n", str_real, data_real);
    }

    fclose(fp);

    return 1;
}

// 从文件读取复数数据并放入指定内存地址
int util_read_complex_number_from_txt_file(char *file_name, int offset, int data_length, float *data_real_ptr, float *data_imag_ptr)
{
    if (data_real_ptr == NULL || data_imag_ptr == NULL || data_length == 0)
    {
        return 0;
    }

    int i = 0;
    char str_real[64];
    char str_symbol[8];
    char str_imag[64];
    float data_real;
    float data_imag;

    FILE *fp = fopen(file_name, "r");
    if (!fp)
    {
        printf("can't open file %s %d\n", file_name, __LINE__);
        return 0;
    }

    i = 0;
    while (!feof(fp))
    {
        fscanf(fp, "%s %s %s", str_real, str_symbol, str_imag);

        if (i < offset)
        {
            i++;
            continue;
        }

        data_real = atof(str_real);
        data_imag = atof(str_imag);
        if (str_symbol[0] == '-')
        {
            data_imag = -data_imag;
        }

        data_real_ptr[i - offset] = data_real;
        data_imag_ptr[i - offset] = data_imag;

        i++;
        if (i >= offset + data_length)
        {
            break;
        }

        // printf("%s %s %s\n", str_real, str_symbol, str_imag);
    }

    fclose(fp);

    return 1;
}

// 将指定内存地址的数据写入文件
int util_write_real_number_to_txt_file(char *file_name, int data_length, uint32 *data_real_ptr)
{
    if (data_real_ptr == NULL || data_length == 0)
    {
        return 0;
    }

    int i = 0;

    FILE *fp = fopen(file_name, "a");
    if (!fp)
    {
        printf("can't open file %s %d\n", file_name, __LINE__);
        return 0;
    }

    for (i = 0; i < data_length; i++)
    {
        fprintf(fp, "%d\n", data_real_ptr[i]);
        if (i == (data_length - 1))
        {
            fprintf(fp, "***\n");
        }
    }

    fclose(fp);

    return 1;
}

// 将指定内存地址的复数数据写入文件
int util_write_complex_number_to_txt_file(char *file_name, int data_length, float *data_real_ptr, float *data_imag_ptr)
{
    if (data_real_ptr == NULL || data_imag_ptr == NULL || data_length == 0)
    {
        return 0;
    }

    int i = 0;

    FILE *fp = fopen(file_name, "a");
    if (!fp)
    {
        printf("can't open file %s %d\n", file_name, __LINE__);
        return 0;
    }

    for (i = 0; i < data_length; i++)
    {
        if (data_imag_ptr[i] >= 0)
        {
            fprintf(fp, "%.6f + %.6fi\n", data_real_ptr[i], data_imag_ptr[i]);
        }
        else if (data_imag_ptr[i] < 0)
        {
            fprintf(fp, "%.6f - %.6fi\n", data_real_ptr[i], fabs(data_imag_ptr[i]));
        }
    }

    fclose(fp);

    return 1;
}

// 将指定内存地址的double数据写入文件
int util_write_double_to_txt_file(char *file_name, int data_length, double *data_double_ptr)
{
    if (data_double_ptr == NULL || data_length == 0)
    {
        return 0;
    }

    int i = 0;

    FILE *fp = fopen(file_name, "a");
    if (!fp)
    {
        printf("can't open file %s %d\n", file_name, __LINE__);
        return 0;
    }

    for (i = 0; i < data_length; i++)
    {
        fprintf(fp, "%.6f\n", data_double_ptr[i]);
    }

    fclose(fp);

    return 1;
}

// 将指定内存地址的int16数据写入文件
// file_name:文件名，绝对路径
// data_length:输入的数据个数
// data_ptr:数据指针
// 返回值:0失败，1成功
int util_write_int16_to_bin_file(char *file_name, int data_length, int16 *data_ptr)
{
    if (data_ptr == NULL || data_length == 0)
    {
        return 0;
    }

    // 以追加的方式打开文件，如果文件不存在则创建文件并写入数据，如果文件已存则追加数据
    FILE *fp = fopen(file_name, "ab");
    if (!fp)
    {
        printf("can't open file %s %d\n", file_name, __LINE__);
        return 0;
    }

    // 写入数据到文件末尾
    int bytesWritten = (int)fwrite(data_ptr, sizeof(int16), data_length, fp);
    if (bytesWritten != data_length)
    {
        fprintf(stderr, "Error writing to file\n");
        fclose(fp);
        return 0;
    }

    fclose(fp);

    return 1;
}

// 从bin文件中读出两字节数据
// filePath:文件绝对路径
// wReadTimes:当前读第几次
// wReadDataLen:读多长数据
// pwOutData:返回参数，数据指针
// 返回值:0失败，1成功
uint8 util_file_read_int16_from_bin_file(char *filePath, uint16 wReadTimes, int16 wReadDataLen, int16 *pwOutData)
{
    if (pwOutData == NULL || wReadDataLen == 0)
    {
        return 0;
    }

    int i = 0;
    int8 byData[2] = {0};
    int16 wData = 0;
    int16 wDataLow = 0;
    int16 wDataHigh = 0;
    uint8 byFlag = 0;

    // 打开文件
    FILE *fp = fopen(filePath, "rb");
    if (!fp)
    {
        printf("open file err\n");
        return 0;
    }

    // 移动文件头指针到偏移处
    byFlag = fseek(fp, wReadTimes * 2 * wReadDataLen, SEEK_SET);
    if (byFlag != RET_OK)
    {
        return 0;
    }

    // 读取文件
    i = 0;
    while (!feof(fp) && i < wReadDataLen)
    {
        memset(byData, 0, 2);
        fread(byData, 1, 2, fp); // 从当前文件指针处每次读一个字节，一共读出两个字节

        wDataLow = byData[0] & 0xff;

        wDataHigh = byData[1] & 0xff;
        wDataHigh <<= 8;

        wData = wDataHigh | wDataLow;

        pwOutData[i] = wData;

        i++;
        if (i >= wReadDataLen)
        {
            break;
        }
    }

    fclose(fp);

    if (i != wReadDataLen)
    {
        return 0;
    }

    return 1;
}

// 将指定内存地址的float数据写入文件
// file_name:文件名，绝对路径
// data_length:输入的数据个数
// data_ptr:数据指针
// byOpenFlag:打开文件的方式，1：wb，2：ab
// 返回值:0失败，1成功
int util_write_flt32_to_bin_file(char *file_name, int data_length, flt32 *data_ptr, uint8 byOpenFlag)
{
    if (data_ptr == NULL || data_length == 0)
    {
        return 0;
    }

    // 打开文件，如果文件不存在则创建文件并写入数据，如果文件已存则追加数据
    FILE *fp = NULL;
    if (byOpenFlag == 1)
    {
        fp = fopen(file_name, "wb");
    }
    else
    {
        fp = fopen(file_name, "ab");
    }

    if (!fp)
    {
        printf("can't open file %s %d\n", file_name, __LINE__);
        return 0;
    }

    // 写入数据到文件末尾
    int bytesWritten = (int)fwrite(data_ptr, sizeof(flt32), data_length, fp);
    if (bytesWritten != data_length)
    {
        fprintf(stderr, "Error writing to file\n");
        fclose(fp);
        return 0;
    }

    fclose(fp);

    return 1;
}

// 将指定内存地址的int数据写入文件
// file_name:文件名，绝对路径
// data_length:输入的数据个数
// data_ptr:数据指针
// 返回值:0失败，1成功
int util_write_coord_to_bin_file(char *file_name, int data_length, uint32 *data_ptr)
{
    if (data_ptr == NULL || data_length == 0)
    {
        return 0;
    }

    // 以追加的方式打开文件，如果文件不存在则创建文件并写入数据，如果文件已存则追加数据
    FILE *fp = fopen(file_name, "ab");
    if (!fp)
    {
        printf("can't open file %s %d\n", file_name, __LINE__);
        return 0;
    }

    // 写入数据到文件末尾
    int bytesWritten = (int)fwrite(data_ptr, sizeof(int), data_length, fp);
    if (bytesWritten != data_length)
    {
        fprintf(stderr, "Error writing to file\n");
        fclose(fp);
        return 0;
    }

    fclose(fp);

    return 1;
}