#include "helpers.h"

QString ip2num(QString input, unsigned char* numbers)
{
    QStringList ip_sl = input.split(".");
    unsigned char ip_arr[4];
    for (int i = 0; i < 4; i++)
        if (i < ip_sl.length())
            ip_arr[i] = (unsigned char) ip_sl.at(i).toInt();
        else
            ip_arr[i] = 0;

    QString generated = QString("%1.%2.%3.%4")
                                .arg(ip_arr[0])
                                .arg(ip_arr[1])
                                .arg(ip_arr[2])
                                .arg(ip_arr[3]);

    if (numbers)
    {
        for (int i = 0; i < 4; i++)
            numbers[i] = ip_arr[i];
    }

    return generated;
}

void top (QSettings* settings)
{
    while(settings->group().length() != 0)
        settings->endGroup();
}


void copyQSettingsHelper(QSettings* from, QSettings* to)
{
        //copy own keys
    QStringList keys = from->childKeys();
    for(int i = 0; i < keys.length(); i++)
    {
       to->setValue(keys[i], from->value(keys[i]));
    }

        //recursively copy child groups
    QStringList groups = from->childGroups();
    for(int i = 0; i < groups.length(); i++)
    {
       from->beginGroup(groups[i]);
       to->beginGroup(groups[i]);

       copyQSettingsHelper(from, to);

       from->endGroup();\
       to->endGroup();
    }
}

void copyQSettings(QSettings* from, QSettings* to)
{
    to->clear();
    top(from);

    copyQSettingsHelper(from, to);
}

void msleep2(unsigned int ms, unsigned int resolution)
{
    QTimer timer;
    timer.setSingleShot(1);
    timer.start(ms);
    while(timer.isActive())
    {
        QCoreApplication::processEvents();
        QThread::msleep(resolution);
    }
}

void saveCsvFile(QString filename, QList<QVector<double>> params, QList<QVector<double>> sensormean, QList<QVector<double>> sensorstd, QString delimiter)
{
    QFile file(filename);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
        return;
    QTextStream out(&file);
    out << qSetFieldWidth(14) << qSetRealNumberPrecision(8);
    for (int row = 0; (row < params.length()) && (row < sensormean.length()) && (row < sensorstd.length()); row++)
    {
        int col;
        for (col = 0; col < params[row].length(); col++)
            out << params[row][col] << delimiter;\

        for (col = 0; (col < (sensormean[row].length() - 1)) && (col < (sensorstd[row].length() - 1)); col++)
            out << sensormean[row][col] << delimiter << sensorstd[row][col] << delimiter;
        out << sensormean[row][col+1] << delimiter << sensorstd[row][col+1] << QString("\n");
    }

    file.close();
}


uint8_t reverseBits(uint8_t byte) {
    uint8_t reversedByte = 0;
    for (int i = 0; i < 8; ++i) {
        reversedByte = (reversedByte << 1) | (byte & 1);
        byte >>= 1;
    }
    return reversedByte;
}

void invertBits(char* buffer, size_t size) {
    if (buffer == nullptr) {
        // Handle error: buffer is null
        return;
    }

    for (size_t i = 0; i < size; ++i) {
        buffer[i] = ~buffer[i]; // Perform bitwise NOT operation
    }
}

void swapEndian(char* buffer, size_t size) {
    for (size_t i = 0; i < size; i += 2) {
        std::swap(buffer[i], buffer[i + 1]);
    }
}
void BYTE2SD(char* mybuffer, BufferData::SensorData& data) {
    // Ensure the buffer has at least 8 bytes
    if (mybuffer == nullptr) {
        // Handle error: buffer is null
        return;
    }

   // // Reverse bits of each byte in the buffer
   // for (size_t i = 0; i < 8; ++i) {
   //     mybuffer[i] = reverseBits(static_cast<uint8_t>(mybuffer[i]));
   // }

    // Invert bits of each byte in the buffer
    invertBits(mybuffer, sizeof(mybuffer));
    swapEndian(mybuffer, sizeof(mybuffer));

    // Combine the first 4 bytes into raw1 and raw2
    uint32_t raw_value;
    std::memcpy(&raw_value, mybuffer, sizeof(raw_value));
    data.raw1 = static_cast<uint16_t>(raw_value & 0xFFFF);        // Lower 16 bits
    data.raw2 = static_cast<uint16_t>((raw_value >> 16) & 0xFFFF); // Upper 16 bits

    // Combine the next 4 bytes into cal1 and cal2
    int32_t cal_value;
    std::memcpy(&cal_value, mybuffer + 4, sizeof(cal_value));
    data.cal1 = static_cast<int16_t>(cal_value & 0xFFFF);        // Lower 16 bits
    data.cal2 = static_cast<int16_t>((cal_value >> 16) & 0xFFFF); // Upper 16 bits
}

void printBufferBits(const char* buffer, size_t size) {
    for (size_t i = 0; i < size; ++i) {
        // Print each byte in binary
        std::bitset<8> bits(static_cast<unsigned char>(buffer[i]));
        std::cerr << bits << ' ';
    }
    std::cerr << std::endl;
}
