#include "Widget.h"
#include "Application.h"
#include "BoostLog.h"
#include "CategoryLogSinkBackend.h"
#include "Database.h"
#include "ModuleCommunication.h"
#include "PalmFeatureTableModel.h"
#include <QComboBox>
#include <QFormLayout>
#include <QGridLayout>
#include <QGroupBox>
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QSerialPortInfo>
#include <QTabWidget>
#include <QTableView>
#include <QTextBrowser>
#include <QTimer>
#include <QVBoxLayout>

Widget::Widget(QWidget *parent) : QWidget{parent} {
    auto serialGroupBox = new QGroupBox("串口设置");
    auto serialLayout = new QGridLayout();

    auto label = new QLabel("端口");
    serialLayout->addWidget(label, 0, 0);

    m_serialComboBox = new QComboBox();
    serialLayout->addWidget(m_serialComboBox, 0, 1);

    label = new QLabel("波特率");
    serialLayout->addWidget(label, 1, 0);

    label = new QLabel("115200");
    serialLayout->addWidget(label, 1, 1);

    auto refreshButton = new QPushButton("刷新");
    connect(refreshButton, &QPushButton::clicked, this, &Widget::onSerialRefreshButtonClicked);
    m_serialConnectButton = new QPushButton("连接");
    connect(m_serialConnectButton, &QPushButton::clicked, this, &Widget::onSerialConnectButtonClicked);
    serialLayout->addWidget(refreshButton, 2, 0);
    serialLayout->addWidget(m_serialConnectButton, 2, 1);
    serialGroupBox->setLayout(serialLayout);

    auto connectLayout = new QHBoxLayout();
    connectLayout->addWidget(serialGroupBox);
    connectLayout->addWidget(initializeUvcGroupBox());

    m_logBrowser = new QTextBrowser();
    m_logBrowser->setReadOnly(true);
    auto logLayout = new QVBoxLayout();
    m_logBrowser->setLayout(logLayout);
    auto btn = new QPushButton("清空");
    connect(btn, &QPushButton::clicked, this, &Widget::onClearLogButtonClicked);
    logLayout->addWidget(btn, 0, Qt::AlignBottom | Qt::AlignRight);

    m_featureTableView = new QTableView();

    auto tabWidget = new QTabWidget();
    tabWidget->addTab(m_logBrowser, "日志");
    tabWidget->addTab(new QWidget(), "视频流");
    tabWidget->addTab(m_featureTableView, "本地特征值列表");

    m_commandGroupBox = initializeCommandGroupBox();

    auto operatorLayout = new QVBoxLayout();
    operatorLayout->addLayout(connectLayout);
    operatorLayout->addWidget(m_commandGroupBox);
    operatorLayout->addStretch(2);

    auto layout = new QHBoxLayout(this);
    layout->addLayout(operatorLayout, 1);
    layout->addWidget(tabWidget, 3);

    m_featureModel = new PalmFeatureTableModel(this);
    m_featureTableView->setModel(m_featureModel);

    QTimer::singleShot(0, this, [this]() {
        onSerialRefreshButtonClicked();
        m_commandGroupBox->setEnabled(false);
    });
}


QGroupBox *Widget::initializeCommandGroupBox() {
    auto ret = new QGroupBox("命令");
    auto layout = new QGridLayout();

    layout->addWidget(initializeEnrollGroupBox(), 0, 0);
    layout->addWidget(initializeVerifyGroupBox(), 0, 1);
    layout->addWidget(initializeDeleteGroupBox(), 1, 0);
    layout->addWidget(initializePalmFeatureGroupBox(), 1, 1);

    auto resetButton = new QPushButton("复位");
    connect(resetButton, &QPushButton::clicked, this, &Widget::onResetButtonClicked);
    layout->addWidget(resetButton, 2, 0);

    ret->setLayout(layout);
    return ret;
}

void Widget::onClearLogButtonClicked() {
    m_logBrowser->clear();
}

QGroupBox *Widget::initializeEnrollGroupBox() {
    auto ret = new QGroupBox("注册用户");
    auto layout = new QFormLayout();

    m_enrollNameEdit = new QLineEdit();
    layout->addRow("用户姓名:", m_enrollNameEdit);

    m_enrollTimeoutEdit = new QLineEdit("10");
    layout->addRow("超时时间:", m_enrollTimeoutEdit);

    m_enrollButton = new QPushButton("注册");
    connect(m_enrollButton, &QPushButton::clicked, this, &Widget::onEnrollButtonClicked);
    layout->addRow("", m_enrollButton);

    auto enrollExButton = new QPushButton("注册(EX)");
    connect(enrollExButton, &QPushButton::clicked, this, &Widget::onEnrollExButtonClicked);
    layout->addRow("", enrollExButton);

    ret->setLayout(layout);
    return ret;
}
QGroupBox *Widget::initializeVerifyGroupBox() {
    auto ret = new QGroupBox("识别用户");
    auto layout = new QFormLayout();

    m_verifyTimeoutEdit = new QLineEdit("10");
    layout->addRow("超时时间:", m_verifyTimeoutEdit);

    m_verifyButton = new QPushButton("识别");
    connect(m_verifyButton, &QPushButton::clicked, this, &Widget::onVerifyButtonClicked);
    layout->addRow("", m_verifyButton);
    ret->setLayout(layout);
    return ret;
}
QGroupBox *Widget::initializeDeleteGroupBox() {
    auto ret = new QGroupBox("删除用户");
    auto layout = new QFormLayout();

    m_deleteIdEdit = new QLineEdit("");
    layout->addRow("用户ID:", m_deleteIdEdit);

    m_deleteButton = new QPushButton("删除");
    connect(m_deleteButton, &QPushButton::clicked, this, &Widget::onDeleteButtonClicked);
    layout->addRow("", m_deleteButton);

    m_deleteAllButton = new QPushButton("删除所有");
    connect(m_deleteAllButton, &QPushButton::clicked, this, &Widget::onDeleteAllButtonClicked);
    layout->addRow("", m_deleteAllButton);

    ret->setLayout(layout);
    return ret;
}
QGroupBox *Widget::initializePalmFeatureGroupBox() {
    auto ret = new QGroupBox("特征值下发/上报");

    auto layout = new QFormLayout();

    m_palmFeatureEdit = new QLineEdit("");
    layout->addRow("用户ID:", m_palmFeatureEdit);

    auto button1 = new QPushButton("特征值上报");
    layout->addRow("", button1);
    connect(button1, &QPushButton::clicked, this, &Widget::onRequestPalmFeatureButtonClicked);

    auto button = new QPushButton("特征值下发");
    connect(button, &QPushButton::clicked, this, &Widget::onRegisterPalmFeatureButtonClicked);
    layout->addRow("", button);

    ret->setLayout(layout);

    return ret;
}

QGroupBox *Widget::initializeUvcGroupBox() {
    auto ret = new QGroupBox("UVC设置");
    auto uvcLayout = new QGridLayout();
    auto label = new QLabel("设备名");
    uvcLayout->addWidget(label, 0, 0);

    auto comboBox = new QComboBox();
    uvcLayout->addWidget(comboBox, 0, 1);

    auto uvcRefreshButton = new QPushButton("刷新");
    auto uvcConnectButton = new QPushButton("连接");
    uvcLayout->addWidget(uvcRefreshButton, 1, 0);
    uvcLayout->addWidget(uvcConnectButton, 1, 1);
    ret->setLayout(uvcLayout);
    return ret;
}

void Widget::onSerialConnectButtonClicked() {
    auto button = dynamic_cast<QPushButton *>(sender());
    if (button == nullptr) return;
    auto text = button->text();
    if (text == "连接") {
        auto portName = m_serialComboBox->currentText();
        auto status = Amass::Singleton<Application>::instance()->open(portName, 2000000);
        if (status) {
            m_commandGroupBox->setEnabled(true);
            button->setText("关闭");
        }
    } else if (text == "关闭") {
        Amass::Singleton<Application>::instance()->close();
        m_commandGroupBox->setEnabled(false);
        button->setText("连接");
    }
}

void Widget::onSerialRefreshButtonClicked() {
    m_serialComboBox->clear();
    auto ports = QSerialPortInfo::availablePorts();
    for (auto &port : ports) {
        if (port.description() == "蓝牙链接上的标准串行") continue;
        m_serialComboBox->addItem(port.portName());
    }
}

void Widget::onUvcRefreshButtonClicked() {
}

void Widget::onEnrollButtonClicked() {
    auto module = Amass::Singleton<Application>::instance()->module();
    if (!module) return;
    auto name = m_enrollNameEdit->text();
    auto timeout = m_enrollTimeoutEdit->text().toInt();
    module->enroll(name.toStdString(), true, timeout);
}

void Widget::onEnrollExButtonClicked() {
    auto module = Amass::Singleton<Application>::instance()->module();
    if (!module) return;
    auto name = m_enrollNameEdit->text();
    auto timeout = m_enrollTimeoutEdit->text().toInt();
    module->enrollExtended(name.toStdString(), true, timeout);
}

void Widget::onVerifyButtonClicked() {
    auto module = Amass::Singleton<Application>::instance()->module();
    if (!module) return;
    auto timeout = m_verifyTimeoutEdit->text().toInt();
    module->verify(timeout);
}

void Widget::onDeleteAllButtonClicked() {
    auto module = Amass::Singleton<Application>::instance()->module();
    if (!module) return;
    module->deleteAll();
}

void Widget::onDeleteButtonClicked() {
    auto module = Amass::Singleton<Application>::instance()->module();
    if (!module) return;
    auto id = m_deleteIdEdit->text().toInt();
    module->deleteUser(id);
}

void Widget::onRequestPalmFeatureButtonClicked() {
    auto module = Amass::Singleton<Application>::instance()->module();
    if (!module) return;
    auto id = m_palmFeatureEdit->text().toInt();
}

void Widget::onRegisterPalmFeatureButtonClicked() {
    auto module = Amass::Singleton<Application>::instance()->module();
    if (!module) return;
    // auto features = m_database->palmFeatures();
    // if (features.empty()) {
    //     LOG(error) << "feature is empty.";
    //     return;
    // }
}

void Widget::onResetButtonClicked() {
    auto module = Amass::Singleton<Application>::instance()->module();
    if (!module) return;
    module->reset();
}

void Widget::onNewLog(const QString &log) {
    m_logBrowser->append(log);
}
