#include "eventhandler.h"
#include "logger.h"
#include "specificheatcomparisonmethodform.h"

EventHandler::EventHandler(QCustomPlot *plot,
                                 QCPItemStraightLine *line1,
                                 QCPItemStraightLine *line2,
                                 QObject *parent)
    : QObject(parent), _plot(plot), _line1(line1), _line2(line2)
    ,_enableFlag(false),_mode(Mode::SelectTwoLines),_menu(new QMenu(_plot))
{
    _plot->setInteractions(QCP::iSelectItems);

    initMenu();
}

#if 0
EventHandler::EventHandler(QCustomPlot *plot, QCPItemStraightLine *line1,
                                 QCPItemStraightLine *line2, QCPGraph*graph,
                                 QObject *parent)
    : QObject(parent), _plot(plot), _line1(line1), _line2(line2),_graph(graph)
    ,_enableFlag(false)
{
    _plot->setInteractions(QCP::iSelectItems);
}
#endif

EventHandler::~EventHandler()
{
}

bool EventHandler::eventFilter(QObject *obj, QEvent *event)
{
    if(!_enableFlag){
        //        qDebug()<<"_enableFlag false.";
        logde<<"eventFilter false.";
#if 0
        if(mPlot){
            mPlot->setCursor(Qt::ArrowCursor);
        }
#endif
        return QObject::eventFilter(obj, event);
    }

    if (obj == _plot)
    {
        if (event->type() == QEvent::MouseMove)
        {
            //            qDebug()<<"mouse move...";

            QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
            QPoint mousePos = mouseEvent->pos();
            //            qDebug()<<"x:"<<mousePos.x();

            bool nearLine1 = isNearLine(_line1, mousePos);
            bool nearLine2 = isNearLine(_line2, mousePos);

            if ((nearLine1 && _line1->visible()) ||
                    (nearLine2 && _line2->visible()))
            {
                _plot->setCursor(Qt::SplitHCursor);
            }
            else
            {
                _plot->setCursor(Qt::ArrowCursor);
            }

            if (_draggingLine)
            {
                double x = _plot->xAxis->pixelToCoord(mousePos.x());
                if(_draggingLine == _line1){
                    emit sigSendLineXCoord(1,x);
                }else{
                    emit sigSendLineXCoord(2,x);
                }
                _draggingLine->point1->setCoords(x, _plot->yAxis->range().lower);
                _draggingLine->point2->setCoords(x, _plot->yAxis->range().upper);
                _plot->replot();
//                updateSelectedRegion();
            }
        }
        else if (event->type() == QEvent::MouseButtonPress)
        {
            //            qDebug()<<"mouse press...";

            if(Mode::SelectTwoLines == _mode){
                QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
                if (mouseEvent->button() == Qt::LeftButton)
                {
                    QPoint mousePos = mouseEvent->pos();
                    if (isNearLine(_line1, mousePos))
                    {
                        _draggingLine = _line1;
                        _line1->setSelected(true);
                    }
                    else if (isNearLine(_line2, mousePos))
                    {
                        _draggingLine = _line2;
                        _line2->setSelected(true);
                    }
                }
            }else{
#if 0
                // 检查是否有选中的曲线
                if (event->button() == Qt::LeftButton && selectedPlottables().size() > 0)
                {
                    // 获取选中的曲线
                    QCPCurve *selectedCurve = qobject_cast<QCPCurve*>(selectedPlottables().first());
                    if (selectedCurve)
                    {
                        // 改变曲线的颜色
                        selectedCurve->setPen(QPen(Qt::green)); // 设置线条颜色为绿色
                        replot(); // 重新绘制
                    }
                }
#endif
            }
        }
        else if (event->type() == QEvent::MouseButtonRelease)
        {
            if (_draggingLine)
            {
                _draggingLine->setSelected(false);
                _draggingLine = nullptr;
            }
        }else  if (event->type() == QEvent::ContextMenu) {
            logde<<"context menu...";

#if 0
            for (QCPAbstractPlottable *plottable : _plot->plottables()) {
                if (plottable->selected()) {
                    std::cout << "选中的曲线: " << plottable->name().toStdString() << std::endl;
                }
            }
#endif
            if(_plot->selectedPlottables().size() > 0){
                logde<<"selected...";
                QCPCurve *curve = qobject_cast<QCPCurve *>(_plot->selectedPlottables().front());
                if(!curve){
                    return QObject::eventFilter(obj, event);
                }

                QContextMenuEvent *contextMenuEvent = static_cast<QContextMenuEvent *>(event);
                _menu->move(contextMenuEvent->globalPos());
                _menu->show();


            }else{
                logde<<"not selected...";
            }
        }
    }
    return QObject::eventFilter(obj, event);
}

void EventHandler::initMenu()
{
    _specificHeatItemAction = new QAction("比热项",_plot);
    _baseLineAction = new QAction("基线",_plot);
    _standardSampleAction = new QAction("标样",_plot);
    _sampleAction = new QAction("样品",_plot);
    _delCurveAction = new QAction("删除当前曲线",_plot);

    _menu->addAction(_delCurveAction);
    _menu->addAction(_specificHeatItemAction);

    QMenu *specificHeatItemMenu = new QMenu(_plot);
    specificHeatItemMenu->addAction(_baseLineAction);
    specificHeatItemMenu->addAction(_standardSampleAction);
    specificHeatItemMenu->addAction(_sampleAction);

    _specificHeatItemAction->setMenu(specificHeatItemMenu);

    connect(_baseLineAction,&QAction::triggered,
            this,&EventHandler::slotBaseLine);
    connect(_standardSampleAction,&QAction::triggered,
            this,&EventHandler::slotStandardSample);
    connect(_sampleAction,&QAction::triggered,
            this,&EventHandler::slotSample);

    connect(_delCurveAction,&QAction::triggered,
            this,&EventHandler::slotDelCurve);

}

bool EventHandler::isNearLine(QCPItemStraightLine *line, const QPoint &pos)
{
    double lineX = line->point1->coords().x();
    int linePixelX = _plot->xAxis->coordToPixel(lineX);
    return qAbs(pos.x() - linePixelX) < 5;
}

void EventHandler::slotBaseLine()
{
    logde<<"slotBaseLine...";

    QCPCurve *curve = qobject_cast<QCPCurve *>(_plot->selectedPlottables().front());
    if(!curve){
        return;
    }
    curve->setPen(QPen(Qt::red));
    _plot->replot();

    emit sigSetCurve(SpecificHeatComparisonMethodForm::CurveType::BaseLine,curve);
}

void EventHandler::slotStandardSample()
{
    QCPCurve *curve = qobject_cast<QCPCurve *>(_plot->selectedPlottables().front());
    if(!curve){
        return;
    }
    curve->setPen(QPen(Qt::darkGreen));
    _plot->replot();

    emit sigSetCurve(SpecificHeatComparisonMethodForm::CurveType::StandardSample,curve);
}

void EventHandler::slotSample()
{
#if 1
    QCPCurve *curve = qobject_cast<QCPCurve *>(_plot->selectedPlottables().front());
    if(!curve){
        return;
    }
    curve->setPen(QPen(Qt::black));
    _plot->replot();
#endif

    emit sigSetCurve(SpecificHeatComparisonMethodForm::CurveType::Sample,curve);
}

void EventHandler::slotDelCurve()
{
    QCPCurve *curve = qobject_cast<QCPCurve *>(_plot->selectedPlottables().front());
    if(!curve){
        return;
    }

    emit sigDelCurve(curve);
}

void EventHandler::updateSelectedRegion()
{
#if 0
    double x1 = _line1->point1->coords().x();
    double x2 = _line1->point1->coords().x();
    if (x1 > x2)
        std::swap(x1, x2);

    // 获取曲线数据
    QVector<double> xData, yData;
    //        mGraph->data()->data(xData, yData);
    auto dataContainer = _graph->data();
    for (auto it = dataContainer->begin(); it != dataContainer->end(); ++it)
    {
        xData.append(it->key);
        yData.append(it->value);
    }

    // 查找对应x位置
    int index1 = findClosestIndex(xData, x1);
    int index2 = findClosestIndex(xData, x2);

    //    qDebug() << "Selected region: [" << xData[index1] << ", " << xData[index2] << "]";
#endif
}

int EventHandler::findClosestIndex(const QVector<double> &data, double target)
{
    auto it = std::min_element(data.begin(), data.end(), [target](double a, double b) {
        return qAbs(a - target) < qAbs(b - target);
    });
    return std::distance(data.begin(), it);
}
