/**
 * @file MainWindow.cpp
 * @brief SkyLink Qt 地面站 - 主窗口实现
 * 
 * @author flowzl
 * @date 2026-01-19
 */

#include "MainWindow.h"
#include "GroundReceiver.h"
#include "DataLogger.h"
#include "DeviceInfoReceiver.h"

#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGroupBox>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QStatusBar>
#include <QFileDialog>
#include <QDateTime>
#include <QMessageBox>
#include <QDebug>
#include <QPixmap>
#include <QPainter>
#include <QDialog>
#include <QDialogButtonBox>
#include <QFormLayout>
#include <QDoubleSpinBox>
#include <QSpinBox>
#include <QComboBox>
#include <QProcess>
#include <QLineEdit>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonObject>
#include <QJsonDocument>
#include <QJsonParseError>
#include <iomanip>
#include <sstream>

MainWindow::MainWindow(QWidget* parent)
    : QMainWindow(parent) {
    
    this->setWindowTitle("SkyLink 地面站 - 实时视频接收系统");
    this->setGeometry(100, 100, 1280, 800);
    
    // 初始化
    init_ui();
    init_connections();
    create_menus();
    
    // 创建接收器（设置parent以确保Qt对象树正确管理）
    receiver_ = std::make_shared<GroundReceiver>(this);
    connect(receiver_.get(), &GroundReceiver::error,
            this, [this](const QString& error_msg) {
                QMessageBox::warning(this, "UDP接收错误", error_msg);
                statusBar()->showMessage("错误: " + error_msg);
            });
    receiver_->start();

    // 设备信息接收器
    device_info_receiver_ = std::make_shared<DeviceInfoReceiver>(this, 10000);
    connect(device_info_receiver_.get(), &DeviceInfoReceiver::deviceInfoReceived,
            this, &MainWindow::on_device_info_received);
    connect(device_info_receiver_.get(), &DeviceInfoReceiver::error,
            this, [this](const QString& msg) {
                statusBar()->showMessage("设备信息错误: " + msg, 2000);
            });
    device_info_receiver_->start();
    device_info_receiver_->request_info();
    
    // 创建记录器
    logger_ = std::make_shared<DataLogger>("./skylink_data");
    
    // 创建网络管理器
    network_manager_ = new QNetworkAccessManager(this);
    connect(network_manager_, &QNetworkAccessManager::finished,
            this, &MainWindow::onHttpReply);
    
    // 连接信号
    bool connected1 = connect(receiver_.get(), qOverload<const QImage&, double, double, double, uint32_t>(&GroundReceiver::frameDecoded),
                               this, &MainWindow::on_frame_received);
    bool connected2 = connect(receiver_.get(), &GroundReceiver::statsUpdated,
                               this, &MainWindow::on_stats_updated);
    
    if (!connected1) {
        qWarning() << "frameDecoded信号连接失败";
    }
    if (!connected2) {
        qWarning() << "statsUpdated信号连接失败";
    }
    
    qDebug() << "信号连接状态 - frameDecoded:" << connected1 << "statsUpdated:" << connected2;
    
    statusBar()->showMessage("就绪，等待数据...");
    
    // 确保窗口显示在最前面
    this->raise();
    this->activateWindow();
}

MainWindow::~MainWindow() {
    if (receiver_) {
        receiver_->stop();
    }
}

void MainWindow::init_ui() {
    // 中央部件
    QWidget* central = new QWidget(this);
    this->setCentralWidget(central);
    
    QVBoxLayout* main_layout = new QVBoxLayout(central);
    
    // ========================================================================
    // 视频显示区
    // ========================================================================
    
    QGroupBox* video_group = new QGroupBox("实时视频", this);
    QVBoxLayout* video_layout = new QVBoxLayout(video_group);
    
    video_label_ = new QLabel(this);
    video_label_->setMinimumSize(640, 480);
    video_label_->setAlignment(Qt::AlignCenter);
    video_label_->setText("等待视频数据...");
    video_label_->setStyleSheet(
        "background-color: #000000; "
        "color: #888888; "
        "border: 2px solid #333333; "
        "font-size: 16px;"
    );
    // 确保标签可以显示图片
    video_label_->setScaledContents(false);  // 不使用自动缩放，我们手动缩放
    video_label_->setTextFormat(Qt::PlainText);
    
    video_layout->addWidget(video_label_);
    main_layout->addWidget(video_group, 1);
    
    // ========================================================================
    // 信息和控制区
    // ========================================================================
    
    QHBoxLayout* info_control_layout = new QHBoxLayout();
    
    // GPS 信息
    QGroupBox* gps_group = new QGroupBox("GPS 信息", this);
    QVBoxLayout* gps_layout = new QVBoxLayout(gps_group);
    gps_label_ = new QLabel("纬度: -- \n经度: --\n海拔: --", this);
    gps_label_->setAlignment(Qt::AlignTop | Qt::AlignLeft);
    gps_layout->addWidget(gps_label_);
    info_control_layout->addWidget(gps_group);
    
    // 统计信息
    QGroupBox* stats_group = new QGroupBox("实时统计", this);
    QVBoxLayout* stats_layout = new QVBoxLayout(stats_group);
    stats_label_ = new QLabel("FPS: 0\n速率: 0 KB/s\n丢包率: 0%", this);
    stats_label_->setAlignment(Qt::AlignTop | Qt::AlignLeft);
    stats_layout->addWidget(stats_label_);
    info_control_layout->addWidget(stats_group);

    // 设备信息
    QGroupBox* device_group = new QGroupBox("设备信息", this);
    QVBoxLayout* device_layout = new QVBoxLayout(device_group);
    device_info_label_ = new QLabel("分辨率: --x--\n帧率: --\n格式: --\n设备: --\n当前FPS: --\n总帧: --", this);
    device_info_label_->setAlignment(Qt::AlignTop | Qt::AlignLeft);
    device_layout->addWidget(device_info_label_);
    info_control_layout->addWidget(device_group);
    
    // 按钮组
    QGroupBox* btn_group = new QGroupBox("控制", this);
    QVBoxLayout* btn_layout = new QVBoxLayout(btn_group);
    
    save_frame_btn_ = new QPushButton("📸 保存帧", this);
    record_btn_ = new QPushButton("⏺ 开始录制", this);
    trigger_capture_btn_ = new QPushButton("📷 触发拍照", this);
    settings_btn_ = new QPushButton("⚙ 设置", this);
    
    record_btn_->setCheckable(true);
    
    btn_layout->addWidget(save_frame_btn_);
    btn_layout->addWidget(record_btn_);
    btn_layout->addWidget(trigger_capture_btn_);
    btn_layout->addWidget(settings_btn_);
    btn_layout->addStretch();
    
    info_control_layout->addWidget(btn_group);
    main_layout->addLayout(info_control_layout);
}

void MainWindow::init_connections() {
    connect(save_frame_btn_, &QPushButton::clicked,
            this, &MainWindow::on_save_frame_clicked);
    
    connect(record_btn_, &QPushButton::toggled,
            this, &MainWindow::on_record_toggled);
    
    connect(settings_btn_, &QPushButton::clicked,
            this, &MainWindow::on_settings_clicked);
    
    connect(trigger_capture_btn_, &QPushButton::clicked,
            this, &MainWindow::on_trigger_capture_clicked);
}

void MainWindow::create_menus() {
    QMenuBar* menu = menuBar();
    
    // 文件菜单
    QMenu* file_menu = menu->addMenu("文件(&F)");
    QAction* exit_action = file_menu->addAction("退出");
    connect(exit_action, &QAction::triggered, this, &QWidget::close);
    
    // 帮助菜单
    QMenu* help_menu = menu->addMenu("帮助(&H)");
    QAction* about_action = help_menu->addAction("关于");
    connect(about_action, &QAction::triggered, [this]() {
        QMessageBox::information(this, "关于",
            "SkyLink 地面站 v1.0\n\n"
            "实时多平台视频传输系统\n"
            "Copyright 2026 flowzl"
        );
    });
}

void MainWindow::on_frame_received(const QImage& img, double lat, double lon, double alt, uint32_t photo_number) {
    // 调试信息
    static int frame_count = 0;
    frame_count++;
    
    if (img.isNull()) {
        qWarning() << "收到空图像，帧计数:" << frame_count;
        statusBar()->showMessage("警告: 收到空图像", 2000);
        return;
    }
    
    qDebug() << "收到图像，帧" << frame_count << "大小:" << img.width() << "x" << img.height()
             << "格式:" << img.format() << "照片编号:" << photo_number;
    
    current_image_ = img;
    current_lat_ = lat;
    current_lon_ = lon;
    current_alt_ = alt;
    current_photo_number_ = photo_number;
    
    if (photo_number > 0) {
        total_photos_received_++;
    }
    
    // 显示图像
    QPixmap pixmap = QPixmap::fromImage(img);
    if (pixmap.isNull()) {
        qWarning() << "QPixmap转换失败";
        statusBar()->showMessage("错误: 图像转换失败", 2000);
        return;
    }
    
    // 获取标签的实际大小（如果为0则使用最小尺寸）
    int w = video_label_->width();
    int h = video_label_->height();
    if (w <= 0) w = 640;
    if (h <= 0) h = 480;
    
    // 缩放并显示
    QPixmap scaled_pixmap = pixmap.scaled(w, h, Qt::KeepAspectRatio, Qt::SmoothTransformation);
    if (scaled_pixmap.isNull()) {
        qWarning() << "图像缩放失败";
        statusBar()->showMessage("错误: 图像缩放失败", 2000);
        return;
    }
    
    // 在图像上叠加显示照片编号
    if (photo_number > 0) {
        QPainter painter(&scaled_pixmap);
        painter.setPen(QPen(Qt::white, 2));
        painter.setFont(QFont("Arial", 16, QFont::Bold));
        QString photo_text = QString("Photo #%1").arg(photo_number);
        QRect textRect = painter.fontMetrics().boundingRect(photo_text);
        painter.fillRect(10, 10, textRect.width() + 10, textRect.height() + 5, QColor(0, 0, 0, 180));
        painter.drawText(15, 10 + textRect.height(), photo_text);
    }
    
    video_label_->setPixmap(scaled_pixmap);
    video_label_->setText("");  // 清除文本，显示图片
    
    // 更新状态栏
    QString status_text = QString("已接收 %1 帧 | 图像: %2x%3")
                         .arg(frame_count)
                         .arg(img.width())
                         .arg(img.height());
    if (photo_number > 0) {
        status_text += QString(" | 照片编号: %1").arg(photo_number);
    }
    statusBar()->showMessage(status_text, 1000);
    
    // 更新 GPS 标签
    std::ostringstream oss;
    oss << std::fixed << std::setprecision(6);
    oss << "纬度: " << lat << "°\n";
    oss << "经度: " << lon << "°\n";
    oss << "海拔: " << std::fixed << std::setprecision(1) << alt << " m";
    gps_label_->setText(QString::fromStdString(oss.str()));
    
    // 如果正在录制，保存帧
    if (is_recording_ && logger_) {
        logger_->save_frame(img, lat, lon, alt);
    }
}

void MainWindow::on_stats_updated(int fps, int kbs) {
    std::ostringstream oss;
    oss << "FPS: " << fps << "\n";
    oss << "速率: " << kbs << " KB/s\n";
    oss << "丢包率: " << "计算中..." << "%";
    if (total_photos_received_ > 0) {
        oss << "\n总照片数: " << total_photos_received_;
    }
    stats_label_->setText(QString::fromStdString(oss.str()));
}

void MainWindow::on_save_frame_clicked() {
    if (current_image_.isNull()) {
        QMessageBox::warning(this, "警告", "还没有接收到图像");
        return;
    }
    
    QString file = QFileDialog::getSaveFileName(this,
        "保存图像", QString(),
        "JPEG Image (*.jpg);;PNG Image (*.png)");
    
    if (!file.isEmpty()) {
        current_image_.save(file);
        statusBar()->showMessage("图像已保存: " + file);
    }
}

void MainWindow::on_record_toggled(bool checked) {
    is_recording_ = checked;
    
    if (checked) {
        record_btn_->setText("⏹ 停止录制");
        statusBar()->showMessage("开始录制...");
    } else {
        record_btn_->setText("⏺ 开始录制");
        statusBar()->showMessage("录制已停止");
    }
}

void MainWindow::on_settings_clicked() {
    QMessageBox::information(this, "设置",
        "设置功能开发中...\n\n"
        "支持的设置项：\n"
        "- UDP 绑定端口\n"
        "- 视频保存路径\n"
        "- 丢包检测\n"
        "- GPS 地图显示"
    );
}

void MainWindow::on_trigger_capture_clicked() {
    // 创建参数输入对话框
    QDialog dialog(this);
    dialog.setWindowTitle("触发拍照");
    dialog.setModal(true);
    
    QFormLayout* form = new QFormLayout(&dialog);
    
    // 总时间
    QDoubleSpinBox* duration_spin = new QDoubleSpinBox(&dialog);
    duration_spin->setRange(0.0, 3600.0);
    duration_spin->setValue(5.0);
    duration_spin->setSuffix(" 秒");
    duration_spin->setDecimals(1);
    form->addRow("总时间 (0=默认):", duration_spin);
    
    // 拍照数量
    QSpinBox* count_spin = new QSpinBox(&dialog);
    count_spin->setRange(0, 1000);
    count_spin->setValue(10);
    count_spin->setSuffix(" 张");
    form->addRow("拍照数量 (0=默认):", count_spin);
    
    // 时间间隔
    QDoubleSpinBox* interval_spin = new QDoubleSpinBox(&dialog);
    interval_spin->setRange(0.0, 60.0);
    interval_spin->setValue(0.5);
    interval_spin->setSuffix(" 秒");
    interval_spin->setDecimals(2);
    form->addRow("时间间隔 (0=自动):", interval_spin);
    
    // 传输模式
    QComboBox* mode_combo = new QComboBox(&dialog);
    mode_combo->addItem("原图", 0);
    mode_combo->addItem("缩略图", 1);
    form->addRow("传输模式:", mode_combo);
    
    // ROS2节点IP地址
    QLineEdit* ip_edit = new QLineEdit(&dialog);
    ip_edit->setText(ros2_node_ip_);
    form->addRow("ROS2节点IP地址:", ip_edit);
    
    // HTTP端口
    QSpinBox* port_spin = new QSpinBox(&dialog);
    port_spin->setRange(1, 65535);
    port_spin->setValue(ros2_http_port_);
    form->addRow("HTTP端口:", port_spin);
    
    QDialogButtonBox* buttonBox = new QDialogButtonBox(
        QDialogButtonBox::Ok | QDialogButtonBox::Cancel,
        Qt::Horizontal, &dialog);
    form->addRow(buttonBox);
    
    connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
    connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
    
    if (dialog.exec() == QDialog::Accepted) {
        double duration = duration_spin->value();
        int count = count_spin->value();
        double interval = interval_spin->value();
        int mode = mode_combo->currentData().toInt();
        
        // 保存IP和端口配置
        ros2_node_ip_ = ip_edit->text();
        ros2_http_port_ = port_spin->value();
        
        // 通过HTTP调用
        triggerCaptureViaHttp(duration, count, interval, mode);
    }
}

void MainWindow::triggerCaptureViaHttp(double duration, int count, double interval, int mode) {
    // 构建JSON请求
    QJsonObject json;
    json["duration"] = duration;
    json["count"] = count;
    json["interval"] = interval;
    json["transmission_mode"] = mode;
    
    QJsonDocument doc(json);
    QByteArray json_data = doc.toJson();
    
    // 构建URL
    QString url_str = QString("http://%1:%2/api/v1/trigger_capture")
                     .arg(ros2_node_ip_)
                     .arg(ros2_http_port_);
    QUrl url(url_str);
    
    // 创建请求
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    request.setRawHeader("User-Agent", "SkyLink-Qt-Station/1.0");
    
    // 发送POST请求
    QNetworkReply* reply = network_manager_->post(request, json_data);
    
    // 设置超时（5秒）
    QTimer::singleShot(5000, reply, &QNetworkReply::abort);
    
    statusBar()->showMessage(QString("正在发送拍照请求到 %1:%2...").arg(ros2_node_ip_).arg(ros2_http_port_), 2000);
}

void MainWindow::onHttpReply(QNetworkReply* reply) {
    if (!reply) {
        return;
    }
    
    // 检查错误
    if (reply->error() != QNetworkReply::NoError) {
        QString error_msg;
        if (reply->error() == QNetworkReply::TimeoutError) {
            error_msg = "请求超时，请检查网络连接和ROS2节点IP地址";
        } else if (reply->error() == QNetworkReply::ConnectionRefusedError) {
            error_msg = QString("连接被拒绝，请确认ROS2节点HTTP服务器正在运行 (http://%1:%2)")
                       .arg(ros2_node_ip_).arg(ros2_http_port_);
        } else {
            error_msg = QString("网络错误: %1").arg(reply->errorString());
        }
        
        QMessageBox::warning(this, "HTTP请求失败", error_msg);
        statusBar()->showMessage("HTTP请求失败", 3000);
        reply->deleteLater();
        return;
    }
    
    // 读取响应
    QByteArray response_data = reply->readAll();
    int status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    
    // 解析JSON响应
    QJsonParseError parse_error;
    QJsonDocument doc = QJsonDocument::fromJson(response_data, &parse_error);
    
    if (parse_error.error != QJsonParseError::NoError) {
        QMessageBox::warning(this, "响应解析错误", 
            QString("无法解析服务器响应:\n%1").arg(QString::fromUtf8(response_data)));
        statusBar()->showMessage("响应解析失败", 3000);
        reply->deleteLater();
        return;
    }
    
    QJsonObject json = doc.object();
    bool success = json["success"].toBool();
    QString message = json["message"].toString();
    int total_photos = json["total_photos"].toInt();
    
    if (status_code == 200 && success) {
        QMessageBox::information(this, "成功", 
            QString("拍照任务已启动！\n\n%1\n\n总照片数: %2")
            .arg(message)
            .arg(total_photos));
        statusBar()->showMessage(QString("拍照任务已启动 - %1").arg(message), 3000);
    } else {
        QMessageBox::warning(this, "请求失败", 
            QString("服务器返回错误:\n%1\n\n状态码: %2")
            .arg(message)
            .arg(status_code));
        statusBar()->showMessage(QString("请求失败: %1").arg(message), 3000);
    }
    
    reply->deleteLater();
}

void MainWindow::on_device_info_received(const DeviceInfo& info) {
    QString text = QString("分辨率: %1 x %2\n帧率: %3\n格式: %4\n设备: %5 (%6)\n当前FPS: %7\n总帧: %8")
                       .arg(info.width)
                       .arg(info.height)
                       .arg(info.framerate, 0, 'f', 1)
                       .arg(info.pixelFormat)
                       .arg(info.deviceName.isEmpty() ? "Unknown" : info.deviceName)
                       .arg(info.devicePath)
                       .arg(info.currentFps, 0, 'f', 1)
                       .arg(info.totalFrames);
    device_info_label_->setText(text);
    statusBar()->showMessage("已更新设备信息", 1000);
}
