//
// Created by Lenn on 2025/10/17.
//

#ifndef TOUCHSENSOR_HEATMAP_IMPL_HH
#define TOUCHSENSOR_HEATMAP_IMPL_HH

#include "heatmap.hh"
#include "modern-qt/utility/theme/theme.hh"
#include "modern-qt/widget/sliders.hh"
#include <memory>
#include <qcolor.h>
#include <qdebug.h>
using namespace creeper::plot_widget::internal;

struct BasicPlot::Impl {
    explicit Impl(BasicPlot& self) noexcept : self{self}, initialized(false), matrix_size(QSize{3, 4}) {}

public:
    auto set_xlabel_text(const QString& text) -> void {
        xlabel = text;
        if (initialized) {
            self.xAxis->setLabel(text);
            self.replot();
        }
    }

    auto set_ylabel_text(const QString& text) -> void {
        ylabel = text;
        if (initialized) {
            self.yAxis->setLabel(text);
            self.replot();
        }
    }

    auto set_matrix_size(const QSize& size) -> void {
        matrix_size = size;
        if (initialized) {
            reset_plot();
            if (!data_points.isEmpty()) {
                set_data(data_points);
            }
        }
    }

    auto load_theme_manager(ThemeManager& mgr) -> void {
        mgr.append_handler(&self, [this](const ThemeManager& mgr) {
            if (initialized) {
                self.replot();
            }
        });
    }

    auto set_color_gradient_range(const double& min, const double& max) -> void {
        if (initialized && self.plottableCount() > 0) {
            auto* cpmp = static_cast<QCPColorMap*>(self.plottable(0));
            cpmp->setDataRange(QCPRange(min, max));
            self.replot();
        }
        color_min = min;
        color_max = max;
    }

    auto set_data(const QVector<PointData>& data) -> void {
        data_points = data;
        if (initialized) {
            update_plot_data();
        }
    }

    auto initialize_plot() -> void {
        if (initialized) return;

QCPColorMap* cpmp = new QCPColorMap(self.xAxis, self.yAxis);
        cpmp->data()->setSize(matrix_size.width(), matrix_size.height());
        cpmp->data()->setRange(QCPRange(0.5, matrix_size.width() - 0.5), 
                             QCPRange(0.5, matrix_size.height() - 0.5));
        
        QSharedPointer<QCPAxisTickerText> xticker(new QCPAxisTickerText);
        QSharedPointer<QCPAxisTickerText> yticker(new QCPAxisTickerText);
        xticker->setSubTickCount(1);
        yticker->setSubTickCount(1);
        self.xAxis->setVisible(false);
        self.yAxis->setVisible(false);
        self.xAxis->setTicker(xticker);
        self.yAxis->setTicker(yticker);

        self.xAxis->grid()->setPen(Qt::NoPen);
        self.yAxis->grid()->setPen(Qt::NoPen);
        self.xAxis->grid()->setSubGridVisible(true);
        self.yAxis->grid()->setSubGridVisible(true);
        self.xAxis->setSubTicks(true);
        self.yAxis->setSubTicks(true);
        self.xAxis->setTickLength(0);
        self.yAxis->setTickLength(0);
        self.xAxis->setSubTickLength(6);
        self.yAxis->setSubTickLength(6);
        

        self.xAxis->setRange(0, matrix_size.width());
        self.yAxis->setRange(0, matrix_size.height());

        if (!xlabel.isEmpty()) self.xAxis->setLabel(xlabel);
        if (!ylabel.isEmpty()) self.yAxis->setLabel(ylabel);
        
        QCPColorScale* color_scale = new QCPColorScale(&self);
        color_scale->setType(QCPAxis::atBottom);
        self.plotLayout()->addElement(1, 0, color_scale);
        cpmp->setColorScale(color_scale);

        QCPColorGradient gradient;
        gradient.setColorStopAt(0.0, QColor(246, 239, 166));  // F6EFA6
        gradient.setColorStopAt(1.0, QColor(191, 68, 76));   // BF444C
        cpmp->setGradient(gradient);

        cpmp->setDataRange(QCPRange(color_min, color_max));
        cpmp->setInterpolate(false);
        
        QCPMarginGroup *margin_group = new QCPMarginGroup(&self);
        self.axisRect()->setMarginGroup(QCP::msLeft | QCP::msRight, margin_group);
        color_scale->setMarginGroup(QCP::msLeft | QCP::msRight, margin_group);
        
        initialized = true;
        
        if (!data_points.isEmpty()) {
            update_plot_data();
        }
    }

    auto reset_plot() -> void {
        // 清除所有绘图元素
        self.clearPlottables();
        self.clearGraphs();
        self.clearItems();
        self.clearFocus();
        
        // 重新初始化
        initialized = false;
        initialize_plot();
    }
    auto update_plot_data() -> void {
        if (!initialized || self.plottableCount() == 0) return;
        
        auto* cpmp = static_cast<QCPColorMap*>(self.plottable(0));
        
        // 设置新数据
        for (const auto& item : data_points) {
            if (item.x >= 0 && item.x < matrix_size.width() && 
                item.y >= 0 && item.y < matrix_size.height()) {
                cpmp->data()->setCell(item.x, item.y, item.z);
            }
        }
        
        // 重绘
        self.replot();
    }

    auto is_plot_initialized() const -> bool {
        return initialized;
    }

    auto get_matrix_size() const -> QSize {
        return matrix_size;
    }

private:
    QString xlabel;
    QString ylabel;
    QSize matrix_size;
    QVector<PointData> data_points;
    double color_min = 0.0;
    double color_max = 800.0;
    bool initialized;
    BasicPlot& self;
};

#endif // TOUCHSENSOR_HEATMAP_IMPL_HH
