#include "CounterWindowRT.h"
#include "ui_CounterWindowRT.h"

CounterWindowRT::CounterWindowRT(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::CounterWindowRT)
{
    ui->setupUi(this);

    this->setWindowFlags(Qt::FramelessWindowHint);
    move(0, 0);
    resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT);

    settingForm = new CounterSettingForm();
    connect(settingForm, &CounterSettingForm::channelSettingSubmit, this, &CounterWindowRT::onChannelSettingSubmit);

    QFile file(":/qss/mainClock.css");
    if (file.open(QFile::ReadOnly)) {
        QString qss = QLatin1String(file.readAll());
        QString paletteColor = qss.mid(20, 7);
        qApp->setPalette(QPalette(QColor(paletteColor)));
        qApp->setStyleSheet(qss);
        file.close();
    }

    ui->labTitle->setText(QString("钟差测量数据采集软件——%1").arg(SettingConfig::getInstance().MASTER == 1 ? "主" : "备"));

    // kafka consumer
    kafkaConsumer = new QKafkaConsumer(this);
    kafkaConsumer->setBrokers(SettingConfig::getInstance().KAFKA_BROKERS);
    kafkaConsumer->setTopic(SettingConfig::getInstance().KAFKA_MSG_TOPIC);
    kafkaConsumer->createConsumer();
    kafkaConsumer->start();
    connect(kafkaConsumer, &QKafkaConsumer::messageRecieved, this, &CounterWindowRT::onKafkaMessageReceived);

    // 绘制界面上的表格
    initChannelForm();

    // 显示时钟 每秒更新
    connect(TimerCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &CounterWindowRT::updateDateAndTime);
    TimerCounterUtil::getInstance().clockCounter->start(1000);

    // 重新选择显示多少个计数器
    connect(settingForm, &CounterSettingForm::swiftDisplayLoop, this, &CounterWindowRT::updateDeviceWidget);
    connect(settingForm, &CounterSettingForm::swiftDisplayCount, this, &CounterWindowRT::initChannelForm);

    httpReq = new HttpRequestController(this);
    // 1. 获取访问接口需要的token
    int retCode = this->initHttpToken();
    if (retCode != 200)
    {
        QMessageBox::information(this, "错误", "获取http请求的token失败，程序即将退出");

        QTimer::singleShot(100, qApp, SLOT(quit()));
    }

    ((QWidget *) ui->widgetContent->children().at(2))->setProperty("form", "devAlarm");
    channelNameList.at(14)->setProperty("labType", "channelNameAlarm");
    channelValueList.at(14)->setProperty("labType", "channelValueAlarm");

    // 初始化设备和通道
    getDeviceList();

    // 查询当前报警记录并显示
    int alarmCount = httpReq->getSysClockAlarmCount();
    if (alarmCount > 0)
    {
        QJsonObject alarmRecords = httpReq->getSysClockAlarmList(alarmCount);
        if (alarmRecords.value("code") == 200)
        {
            this->updateDeviceAlarm(alarmRecords.value("data").toObject().value("rows").toArray());
        }
    }

    // 暂停三秒后打开计数器的串口接收数据
    QThread::msleep(1000 * 3);
    for (int i = 0; i < ConstCache::getInstance().deviceIdLoopA.size(); i++)
    {
        CounterDevice * devicePtr = ConstCache::getInstance().deviceMap.value(ConstCache::getInstance().deviceIdLoopA.at(i));
        devicePtr->initSerialPort();
    }
    for (int i = 0; i < ConstCache::getInstance().deviceIdLoopB.size(); i++)
    {
        CounterDevice * devicePtr = ConstCache::getInstance().deviceMap.value(ConstCache::getInstance().deviceIdLoopB.at(i));
        devicePtr->initSerialPort();
    }
}

CounterWindowRT::~CounterWindowRT()
{
    delete ui;
}

void CounterWindowRT::keyPressEvent(QKeyEvent *event)
{
    switch (event->key()) {
    case Qt::Key_Escape:
        QTimer::singleShot(100, qApp, SLOT(quit()));

    default:
        QWidget::keyPressEvent(event);
    }
}

void CounterWindowRT::onChannelSettingSubmit(QJsonArray channelSettings)
{
    httpReq->updateChannelInfo(channelSettings);
}

int CounterWindowRT::initHttpToken()
{
    QJsonObject response = httpReq->getTokenByClientId(SettingConfig::getInstance().CLIENT_ID,
                                                       SettingConfig::getInstance().APP_KEY);
    return response.value("code").toInt();
}
void CounterWindowRT::getDeviceList()
{
    QJsonObject devListRes = httpReq->initDeviceList(SettingConfig::getInstance().DEV_TYPES, SettingConfig::getInstance().SYSTEM);
    if (devListRes.value("code").toInt() == 200)
    {
        // 将获取到的设备绘制到表格中
        QJsonArray devArray = devListRes.value("data").toArray();
        for (int i = 0; i < devArray.size(); i++)
        {
            // 接口返回的device对象
            QJsonObject devItem = devArray.at(i).toObject();
            QString devName = devItem.value("simpleName").toString(); // 设备名称
            QString deviceId = devItem.value("deviceId").toString(); // 设备ID
            QString isUse = devItem.value("isUse").toString(); // 标识A路/B路

            // 构建Device对象 并赋值id、串口、波特率、设备编号等属性
            CounterDevice * device = new CounterDevice(this);
            device->setDeviceId(deviceId);
            device->setComName(devItem.value("linkComName").toString());
            device->setBaudRate(SettingConfig::getInstance().BAUD_RATE);
            device->setDevCode(devItem.value("deviceNo").toString());
            device->setDeviceName(devName);
            device->setIsUse(isUse.toInt());

            ConstCache::getInstance().deviceMap.insert(deviceId, device);
            if (isUse == "1")
            {
                ConstCache::getInstance().deviceIdLoopA.append(deviceId);
            } else if (isUse == "0") {
                ConstCache::getInstance().deviceIdLoopB.append(deviceId);
            }

            // 绑定显示函数
            connect(device, &CounterDevice::sendDataToDraw, this, &CounterWindowRT::drawCounterDataOnPage);

            // 查询计数器的通道 并初始化串口
            this->getChannelList(deviceId);
        }

        updateDeviceWidget();
    }
}
void CounterWindowRT::getChannelList(QString deviceId)
{
    // 查询计数器的通道
    QJsonObject response = httpReq->getChannelList(deviceId);
    if (response.value("code").toInt() == 200)
    {
        // 将通道绘制在界面上
        QJsonArray channelArray = response.value("data").toArray();
        for (int i = 0; i < channelArray.size(); i++)
        {
            // 接口返回的channel对象
            QJsonObject channelItem = channelArray.at(i).toObject();
            QString channelId = channelItem.value("id").toString(); // 通道ID
            QString channelCode = channelItem.value("channelCode").toString(); // 通道钟号
            QString channelNo = QString::number(channelItem.value("channelNo").toInt()); // 通道序号
            QString delays = channelItem.value("delays").toString(); // 通道时延值
            QString isUse = channelItem.value("isUse").toString();
            QString name = channelItem.value("name").toString();
            bool active = channelItem.value("isActive").toString().toInt(); // 通道是否启用

            // 构建通道对象 并设置属性
            CounterChannel * channel = new CounterChannel(this);
            channel->setDeviceId(deviceId);
            channel->setChannelId(channelId);
            channel->setChannelCode(channelCode);
            channel->setChannelNo(channelNo);
            channel->setDelays(delays);
            channel->setActive(active);
            channel->setIsUse(isUse);
            channel->setName(name);

            // 添加到通道的集合中 key=deviceId-channelNo
            ConstCache::getInstance().channelMap.insert(deviceId + "-" + channelNo, channel);
        }
    }
}

void CounterWindowRT::initDevAndChannelForm(int count)
{
    // 2. 绘制4个计数器的线框，每个计数器显示16个通道
    QHBoxLayout * layoutConter = new QHBoxLayout(ui->widgetContent); // 计数器框采用水平布局
    layoutConter->setSpacing(10); // 设置计数器设备框之间的间隔为10px
    layoutConter->setContentsMargins(15, 0, 15, 20);
    for ( int i = 0; i < count; i++)
    {
        // 计数器对应的wideget
        QWidget * widgetDev = new QWidget(ui->widgetContent);
        widgetDev->setProperty("form", "dev"); // 添加属性，用于css样式选择
        layoutConter->addWidget(widgetDev);

        // 每个计数器框内为左右布局
        QHBoxLayout * layoutChannelPage = new QHBoxLayout(widgetDev);
        layoutChannelPage->setSpacing(0); // 中间不需要间隔
        layoutChannelPage->setMargin(3); // 留出边框的位置

        // 左右布局中是垂直布局，用于显示通道
        QVBoxLayout * layoutChannelLeft = new QVBoxLayout();
        QVBoxLayout * layoutChannelRight = new QVBoxLayout();

        layoutChannelLeft->setSpacing(0);
        layoutChannelRight->setSpacing(0);

        // 设备标题的Label
        QLabel * labDevTitle = new QLabel(widgetDev);
        labDevTitle->setProperty("labType", QString("devTitle%1").arg(count)); // 样式表属性
        labDevTitle->setText(QString("计数器-%1").arg(i + 1));
        labDevTitle->setAlignment(Qt::AlignCenter); // 文字居中显示
        labDevTitle->setStyleSheet("border-top-left-radius: 10px;"); // 左上角的圆角
        devTitleList.append(labDevTitle);

        // 设备参考通道的Label
        QLabel * labDevRef = new QLabel(widgetDev);
        labDevRef->setProperty("labType", QString("devTitle%1").arg(count)); // 样式表属性
        labDevRef->setText(QString("REF: %1").arg("1000"));
        labDevRef->setAlignment(Qt::AlignCenter); // 文字居中显示
        labDevRef->setStyleSheet("border-top-right-radius: 10px;"); // 右上角的圆角
        devRefList.append(labDevRef);

        if (count == 4) {
            labDevTitle->setMaximumHeight(80); // 设置固定高度
            labDevTitle->setMinimumHeight(80);

            labDevRef->setMaximumHeight(80); // 设置固定高度
            labDevRef->setMinimumHeight(80);
        } else {
            labDevTitle->setMaximumHeight(60); // 设置固定高度
            labDevTitle->setMinimumHeight(60);

            labDevRef->setMaximumHeight(60); // 设置固定高度
            labDevRef->setMinimumHeight(60);
        }

        // 左侧显示设备简称，右侧显示参考通道名
        layoutChannelLeft->addWidget(labDevTitle);
        layoutChannelRight->addWidget(labDevRef);

        // 每个计数器显示16个通道
        for ( int i = 0; i < 16; i++ )
        {
            QLabelDblClick * labChannelName = new QLabelDblClick(widgetDev); // 通道名
            QLabelDblClick * labChannelValue = new QLabelDblClick(widgetDev); // 通道测量值

            // 默认显示内容
            labChannelName->setText(QString("CH%1").arg(i+1, 2, 10, QLatin1Char('0')));
            labChannelValue->setText("0.000000000000");

            // css不支持的样式用代码实现
            labChannelName->setMargin(10);
            labChannelValue->setMargin(10);
            labChannelValue->setAlignment(Qt::AlignRight | Qt::AlignVCenter);

            // 奇偶显示不同的背景色
            if (i % 2 == 0)
            {
                labChannelName->setProperty("labType", QString("channelNameEven%1").arg(count));
                labChannelValue->setProperty("labType", QString("channelValueEven%1").arg(count));
            } else {
                labChannelName->setProperty("labType", QString("channelNameOdd%1").arg(count));
                labChannelValue->setProperty("labType", QString("channelValueOdd%1").arg(count));
            }

            layoutChannelLeft->addWidget(labChannelName);
            layoutChannelRight->addWidget(labChannelValue);

            // 添加通道名称的双击事件，显示数据和残差图表
            connect(labChannelName, &QLabelDblClick::doubleClicked, this, &CounterWindowRT::onChannelNameLabelDblClicked);
            connect(labChannelValue, &QLabelDblClick::doubleClicked, this, &CounterWindowRT::onChannelNameLabelDblClicked);

            channelNameList.append(labChannelName);
            channelValueList.append(labChannelValue);

            // 左下角和右下角的圆角处理
            if (i == 15) {
                labChannelName->setStyleSheet("border-bottom-left-radius: 10px;");
                labChannelValue->setStyleSheet("border-bottom-right-radius: 10px;");
            }
        }

        layoutChannelPage->addLayout(layoutChannelLeft);
        layoutChannelPage->addLayout(layoutChannelRight);
        widgetDev->setLayout(layoutChannelPage);
    }
}
void CounterWindowRT::updateChannelDataForm(QJsonArray messageArray)
{
    // 获取设备id属性
    QString deviceId = messageArray.at(0).toObject().value("deviceId").toString();

    // 参考通道号
    int refChNo = messageArray.at(0).toObject().value("data").toObject().value("channelRefNo").toInt();

    // 根据设备id 从map中取出列索引的值
    int devIdx = ConstCache::getInstance().deviceMap.value(deviceId)->getFormColIndex();

    if (devIdx < devRefList.size()) {
        // 参考通道的显示
        QString refText = devRefList.at(devIdx)->text();
        channelNameList.at(devIdx * 16 + refChNo - 1)->setText(QString("CH%1：%2").arg(refChNo, 2, 10, QLatin1Char('0')).arg(refText.right(refText.length() - 4)));
    }

    QMap<QString, QJsonObject> channelDataJsonMap;
    for (int i = 0; i < messageArray.size(); i++)
    {
        QJsonObject channelDataItem = messageArray.at(i).toObject();
        QString channelNo = QString::number(channelDataItem.value("channelNo").toInt()); // 通道序号
        channelDataJsonMap.insert(channelNo, channelDataItem);
    }

    CounterChannel * refChanPtr = ConstCache::getInstance().channelMap.value(QString("%1-%2").arg(deviceId).arg(refChNo));
    double refDelay = 0.0;
    if (refChanPtr != nullptr && refChanPtr->getDelays().isEmpty() == false) {
        refDelay = refChanPtr->getDelays().toDouble();
    }

    // 逐个通道显示
    for (int i = 0; i < 16; i++)
    {
        QString channelNo = QString::number(i + 1);
        QString channelNoStr = QString("%1").arg(i + 1, 2, 10, QLatin1Char('0'));

        if (i + 1 == refChNo)
        {
            continue;
        }

        if (channelDataJsonMap.contains(channelNo) == true)
        {
            QJsonObject channelDataItem = channelDataJsonMap.value(channelNo);
            CounterChannel * channel = ConstCache::getInstance().channelMap.value(deviceId + "-" + channelNo); // 从map中找到对应的通道

            // 通道Label的序号
            int chanelIdx = devIdx * 16 + channelDataItem.value("channelNo").toInt() - 1;

            if (channel != nullptr && channel->isActive() == true)
            {
                // 通道时延值 并计算 减去时延值的测量值
                double delay = channel->getDelays().isEmpty() == false ? channel->getDelays().toDouble() : 0.0;
                double valueMinusDelay = channelDataItem.value("data").toObject().value("dataValue").toString().toDouble() - delay * 1E-9 + refDelay * 1E-9;

                // 设置通道名和测量值的QLabel
                channelNameList.at(chanelIdx)->setText(QString("CH%1：%2").arg(channelNoStr).arg(channel->getChannelCode()));
                channelValueList.at(chanelIdx)->setText(QString::number(valueMinusDelay, 'f', 12));

                channelNameList.at(chanelIdx)->setProperty("channelId", channel->getChannelId());
                channelNameList.at(chanelIdx)->setProperty("deviceId", deviceId);
                channelNameList.at(chanelIdx)->setProperty("channelNo", channelNo);

                channelValueList.at(chanelIdx)->setProperty("channelId", channel->getChannelId());
                channelValueList.at(chanelIdx)->setProperty("deviceId", deviceId);
                channelValueList.at(chanelIdx)->setProperty("channelNo", channelNo);
            } else {
                channelNameList.at(chanelIdx)->setText(QString("CH%1：%2").arg(channelNoStr).arg("-"));
                channelValueList.at(chanelIdx)->setText("");
            }
        } else {
            // 没有测量值的通道清空
            channelNameList.at(devIdx * 16 + i)->setText(QString("CH%1：%2").arg(channelNoStr).arg("-"));
            channelValueList.at(devIdx * 16 + i)->setText("");

            channelNameList.at(devIdx * 16 + i)->setProperty("labType", "channelNameAlarm");
            channelValueList.at(devIdx * 16 + i)->setProperty("labType", "channelValueAlarm");
        }
    }
}

void CounterWindowRT::updateDeviceAlarm(QJsonArray alarmList)
{
    QVector<QString> alarmDev;
    QVector<QString> alarmChannel;
    for (int i = 0; i < alarmList.size(); i++)
    {
        QJsonObject alarmData = alarmList.at(i).toObject();
        QString deviceId = alarmData.value("deviceId").toString();
        QString channelId = alarmData.value("channelId").toString();
        QString level = alarmData.value("level").toString();
        QString status = alarmData.value("status").toString();

        if (alarmDev.contains(deviceId) == false) {
            alarmDev.append(deviceId);
        }
//        CounterChannel *
    }

    for (int i = 0; i < alarmDev.size(); i++)
    {
        CounterDevice * devicePtr = ConstCache::getInstance().deviceMap.value(alarmDev.at(i));
        if (devicePtr != nullptr)
        {
            if (settingForm->getDisplayGroupFlag() == 1)
            {
                if (ConstCache::getInstance().deviceIdLoopA.contains(alarmDev.at(i)))
                {
                    ((QWidget *)ui->widgetContent->children().at(devicePtr->getFormColIndex() + 1))->setProperty("form", "devAlarm");
                }
            } else if (settingForm->getDisplayGroupFlag() == 0)
            {
                if (ConstCache::getInstance().deviceIdLoopB.contains(alarmDev.at(i)))
                {
                    qDebug() << "B: " << devicePtr->getFormColIndex() << ui->widgetContent->children().size();

                }
            }
        }
    }
}

CounterChannel * CounterWindowRT::getChannelByDevAndId(QString deviceId, QString channelId)
{
    if (deviceId.isEmpty() == true || channelId.isEmpty() == true)
        return nullptr;

    for (int i = 1; i <= 16; i++)
    {
        QString key = QString("%1-%2").arg(deviceId).arg(i);
        CounterChannel * channelPtr = ConstCache::getInstance().channelMap.value(key);
        if (channelPtr != nullptr) {
            if (channelPtr->getChannelId() == channelId)
            {
                return channelPtr;
            }
        }
    }

    return nullptr;
}

void CounterWindowRT::updateDateAndTime()
{
    QString date = QDate::currentDate().toString("yyyy-MM-dd");
    QString time = QTime::currentTime().toString("HH:mm:ss");
    ui->labTime->setText(date + " " + time);
}

void CounterWindowRT::on_btnMenuSetting_clicked()
{
    settingForm->setWindowModality(Qt::ApplicationModal);
    settingForm->setWindowTitle("系统设置");
    settingForm->initCounterSelect();
    settingForm->show();
}
void CounterWindowRT::on_btnMenuMin_clicked()
{
    setWindowState(Qt::WindowMinimized | windowState());
}

void CounterWindowRT::initChannelForm()
{
    // 1. 首先清除界面上的所有内容
    qDeleteAll(ui->widgetContent->children());

    // 将lab列表的数量置0
    devTitleList.resize(0);
    devRefList.resize(0);
    channelNameList.resize(0);
    channelValueList.resize(0);

    initDevAndChannelForm(SettingConfig::getInstance().DISPLAY_COUNT);
}

void CounterWindowRT::updateDeviceWidget()
{
    QList<QString> devIds = SettingConfig::getInstance().MASTER == 1 ? ConstCache::getInstance().deviceIdLoopA : ConstCache::getInstance().deviceIdLoopB;

    for (int i = 0; i < SettingConfig::getInstance().DISPLAY_COUNT; i++)
    {
        if (i < devIds.size())
        {
            CounterDevice * dev = ConstCache::getInstance().deviceMap.value(devIds.at(i));

            if (dev != nullptr) {
                devTitleList.at(i)->setText(dev->getDeviceName()); // 设备名称
                dev->setFormColIndex(i);
            }
        } else {
            devTitleList.at(i)->setText("");
            devRefList.at(i)->setText("");

            for (int j = 0; j < 16; j++)
            {
                channelNameList.at(i * 16 + j)->setText("");
                channelValueList.at(i * 16 + j)->setText("");
            }
        }
    }
}

void CounterWindowRT::onChannelNameLabelDblClicked()
{
    QLabelDblClick * channelLab = (QLabelDblClick *) sender();
    QString deviceId = channelLab->property("deviceId").toString();
    QString channelNo = channelLab->property("channelNo").toString();

    CounterChannel * channel = ConstCache::getInstance().channelMap.value(deviceId + "-" + channelNo);
    if (channel != nullptr)
    {
        CounterDevice * device = ConstCache::getInstance().deviceMap.value(deviceId);
        QString deviceName = device != nullptr ? device->getDeviceName() : "";

        ChannelChartForm * chartFrame = new ChannelChartForm();
        chartFrame->setWindowModality(Qt::ApplicationModal);
        chartFrame->initDataChart(channel->getHisData());
        chartFrame->setTitleText((QString("%1 通道%2 历史数据").arg(deviceName).arg(channelNo)));
        chartFrame->show();
    }
}


/**
 * @brief CounterWindowRT::drawCounterDataOnPage
 * @param messageArray
 * 根据发送到Kafka中的数据串来绘制界面
 *
 */
void CounterWindowRT::drawCounterDataOnPage(QJsonArray messageArray)
{
    if (messageArray.isEmpty() == false)
    {
        // 获取设备id属性
        QString deviceId = messageArray.at(0).toObject().value("deviceId").toString();

        // 如果不是当前显示的计数器 则直接返回
        CounterDevice * devicePtr = ConstCache::getInstance().deviceMap.value(deviceId);
        if (devicePtr == nullptr || SettingConfig::getInstance().MASTER != devicePtr->getIsUse())
        {
            return;
        }

        // 根据设备id 从map中取出列索引的值
        int devIdx = devicePtr->getFormColIndex();
        if (devIdx > SettingConfig::getInstance().DISPLAY_COUNT)
        {
            return;
        }

        // 参考通道
        int refChNo = messageArray.at(0).toObject().value("data").toObject().value("channelRefNo").toInt();
        CounterChannel * refChann = ConstCache::getInstance().channelMap.value(QString("%1-%2").arg(deviceId).arg(refChNo));
        if (refChann != nullptr)
        {
            if (devIdx < devRefList.size()) {
                devRefList.at(devIdx)->setText(QString("REF：%1").arg(refChann->getChannelCode()));
            }
        }

        updateChannelDataForm(messageArray);
    }
}


void CounterWindowRT::onKafkaMessageReceived(QJsonObject message)
{
    qDebug() << message;
    std::cout << QString(QJsonDocument(message).toJson(QJsonDocument::Compact)).toStdString() << std::endl;

    // 找不到deviceId deviceType operation三个必填项 直接返回
    if (message.contains("deviceId") == false || message.contains("operation") == false || message.contains("deviceType") == false) {
        return;
    }

    // deviceType不是计数器 直接返回
    if (message.value("deviceType").toString() != "01") {
        return;
    }

    QString deviceId = message.value("deviceId").toString();

    if (message.contains("chanelId") == true)
    {
        this->getChannelList(deviceId);
    } else
    {
        ConstCache::getInstance().channelMap.clear();
        ConstCache::getInstance().deviceMap.clear();
        this->getDeviceList();
    }
}
