#include "popviewwindow.h"
#include <QLabel>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QToolBar>
#include <QPushButton>
#include <QGraphicsDropShadowEffect>
#include <QPainter>
#include <QApplication>
#include "canvas.h"
#include <QDebug>


static QIcon coloredIcon(const QIcon &iIcon, const QColor &iColor)
{
    QPixmap pixmap = iIcon.pixmap(128, 128);
    if (!pixmap.isNull()){
        QPainter painter(&pixmap);
        painter.setCompositionMode(QPainter::CompositionMode_SourceIn);
        painter.fillRect(pixmap.rect(), iColor);
        painter.end();
    }
    return QIcon(pixmap);
}

class PcbCamPopViewWindowPrivate
{
    Q_DECLARE_PUBLIC(PcbCamPopViewWindow)
public:
    explicit PcbCamPopViewWindowPrivate(PcbCamPopViewWindow *qptr) : q_ptr(qptr){}
    ~PcbCamPopViewWindowPrivate(){}

    enum MouseRegion {
        NONE = 0, UP=1, DOWN=2, LEFT, RIGHT, LEFTTOP, LEFTBOTTOM, RIGHTBOTTOM, RIGHTTOP
    };

    QLabel *imageLabel {nullptr};
    PcbCamCanvas *canvas;
    QRectF sourceRect;
    bool isLeftPressDown {false};
    QPoint dragPosition;
    MouseRegion mouseRegion = {NONE};
    int borderPadding = 4;

    void region(const QPoint &cursorGlobalPoint) {
        Q_Q(PcbCamPopViewWindow);
        auto rect = q->rect();
        auto tl = q->mapToGlobal(rect.topLeft());
        auto rb = q->mapToGlobal(rect.bottomRight());

        int x = cursorGlobalPoint.x();
        int y = cursorGlobalPoint.y();

        if(tl.x() + borderPadding >= x && tl.x() <= x && tl.y() + borderPadding >= y && tl.y() <= y) {
            // 左上角
            mouseRegion = LEFTTOP;
            q->setCursor(QCursor(Qt::SizeFDiagCursor));  // 设置鼠标形状
        } else if(x >= rb.x() - borderPadding && x <= rb.x() && y >= rb.y() - borderPadding && y <= rb.y()) {
            // 右下角
            mouseRegion = RIGHTBOTTOM;
            q->setCursor(QCursor(Qt::SizeFDiagCursor));
        } else if(x <= tl.x() + borderPadding && x >= tl.x() && y >= rb.y() - borderPadding && y <= rb.y()) {
            //左下角
            mouseRegion = LEFTBOTTOM;
            q->setCursor(QCursor(Qt::SizeBDiagCursor));
        } else if(x <= rb.x() && x >= rb.x() - borderPadding && y >= tl.y() && y <= tl.y() + borderPadding) {
            // 右上角
            mouseRegion = RIGHTTOP;
            q->setCursor(QCursor(Qt::SizeBDiagCursor));
        } else if(x <= tl.x() + borderPadding && x >= tl.x()) {
            // 左边
            mouseRegion = LEFT;
            q->setCursor(QCursor(Qt::SizeHorCursor));
        } else if( x <= rb.x() && x >= rb.x() - borderPadding) {
            // 右边
            mouseRegion = RIGHT;
            q->setCursor(QCursor(Qt::SizeHorCursor));
        }else if(y >= tl.y() && y <= tl.y() + borderPadding){
            // 上边
            mouseRegion = UP;
            q->setCursor(QCursor(Qt::SizeVerCursor));
        } else if(y <= rb.y() && y >= rb.y() - borderPadding) {
            // 下边
            mouseRegion = DOWN;
            q->setCursor(QCursor(Qt::SizeVerCursor));
        }else {
            // 默认
            mouseRegion = NONE;
            q->setCursor(QCursor(Qt::ArrowCursor));
        }
    }



protected:
    PcbCamPopViewWindow * const q_ptr;
};


PcbCamPopViewWindow::PcbCamPopViewWindow(const QRectF &iSourceRect, const QRect &iTargetRect, PcbCamCanvas *iCanvas): QFrame(iCanvas),
    d_ptr(new PcbCamPopViewWindowPrivate(this))
{
    Q_D(PcbCamPopViewWindow);
    this->setWindowTitle(" ");
    d->canvas = iCanvas;
    d->sourceRect = iSourceRect;

    this->setWindowFlags(Qt::FramelessWindowHint|Qt::Tool);
    this->setMouseTracking(true);

    auto vlayout = new QVBoxLayout(this);
    vlayout->setContentsMargins(0, 0, 0, 0);
    vlayout->setSpacing(0);

    auto tbframe = new QFrame(this);
    tbframe->setMouseTracking(true);
    tbframe->setStyleSheet(".QFrame{background-color:#2F3E4E;}");
    auto tbshadow = new QGraphicsDropShadowEffect(tbframe);
    tbshadow->setBlurRadius(5.0);
    tbshadow->setOffset(1.0, 1.0);
    tbframe->setGraphicsEffect(tbshadow);
    auto tblayout = new QHBoxLayout(tbframe);
    tblayout->setContentsMargins(2, 2, 2, 2);
    tblayout->setSpacing(4);
    vlayout->addWidget(tbframe, 0);

    auto imagelayout = new QVBoxLayout;
    imagelayout->setContentsMargins(2, 2, 2, 2);
    imagelayout->setSpacing(0);
    d->imageLabel = new QLabel(this);
    d->imageLabel->setMouseTracking(true);
    d->imageLabel->setMinimumSize(100, 100);
    imagelayout->addWidget(d->imageLabel, 1);
    vlayout->addLayout(imagelayout, 1);

    QColor iconColor = Qt::white;
    auto viewUpBtn = new QPushButton(coloredIcon(QIcon("./res/icon/view_up.svg"), iconColor), "", this);
    viewUpBtn->setToolTip(tr("Pan Up"));
    viewUpBtn->setProperty("SS_TYPE", "DARKTOOL");
    viewUpBtn->setProperty("SS_SIZE", "SMALL");

    auto viewDownBtn = new QPushButton(coloredIcon(QIcon("./res/icon/view_down.svg"), iconColor) ,"", this);
    viewDownBtn->setToolTip(tr("Pan Down"));
    viewDownBtn->setProperty("SS_TYPE", "DARKTOOL");
    viewDownBtn->setProperty("SS_SIZE", "SMALL");

    auto viewLeftBtn = new QPushButton(coloredIcon(QIcon("./res/icon/view_left.svg"), iconColor),"", this);
    viewLeftBtn->setProperty("SS_TYPE", "DARKTOOL");
    viewLeftBtn->setProperty("SS_SIZE", "SMALL");
    viewLeftBtn->setToolTip(tr("Pan Left"));

    auto viewRightBtn = new QPushButton(coloredIcon(QIcon("./res/icon/view_right.svg"), iconColor) ,"", this);
    viewRightBtn->setToolTip(tr("Pan Down"));
    viewRightBtn->setProperty("SS_TYPE", "DARKTOOL");
    viewRightBtn->setProperty("SS_SIZE", "SMALL");

    auto zoomInBtn = new QPushButton(coloredIcon(QIcon("./res/icon/zoom_in.svg"), iconColor),"", this);
    zoomInBtn->setToolTip(tr("Zoom In"));
    zoomInBtn->setProperty("SS_TYPE", "DARKTOOL");
    zoomInBtn->setProperty("SS_SIZE", "SMALL");

    auto zoomOutBtn = new QPushButton(coloredIcon(QIcon("./res/icon/zoom_out.svg"), iconColor),"", this);
    zoomOutBtn->setToolTip(tr("Zoom Out"));
    zoomOutBtn->setProperty("SS_TYPE", "DARKTOOL");
    zoomOutBtn->setProperty("SS_SIZE", "SMALL");

    auto closeBtn = new QPushButton(coloredIcon(QIcon("./res/icon/close.svg"), iconColor), "", this);
    closeBtn->setToolTip(tr("Close"));
    closeBtn->setProperty("SS_TYPE", "DARKTOOL");
    closeBtn->setProperty("SS_SIZE", "SMALL");


    tblayout->addSpacing(2);
    tblayout->addWidget(viewUpBtn, 0);
    tblayout->addWidget(viewDownBtn, 0);
    tblayout->addWidget(viewLeftBtn, 0);
    tblayout->addWidget(viewRightBtn, 0);
    tblayout->addWidget(zoomInBtn, 0);
    tblayout->addWidget(zoomOutBtn, 0);
    tblayout->addStretch(1);
    tblayout->addWidget(closeBtn, 0);

    this->adjustSize();
    QSize imgsize = d->imageLabel->size();
    QSize winsize = this->size();
    QPoint imgpos = this->mapToGlobal(d->imageLabel->rect().topLeft());
    int sx = winsize.width() - imgsize.width();
    int sy = winsize.height() - imgsize.height();
    this->setGeometry(QRect(iTargetRect.topLeft() - imgpos, QSize(iTargetRect.size().width() + sx, iTargetRect.size().height() + sy)));

    tbframe->raise();

    connect(closeBtn, &QPushButton::clicked, this, &PcbCamPopViewWindow::close);
    connect(viewUpBtn, &QPushButton::clicked, this, &PcbCamPopViewWindow::onPanUpClicked);
    connect(viewDownBtn, &QPushButton::clicked, this, &PcbCamPopViewWindow::onPanDownClicked);
    connect(viewLeftBtn, &QPushButton::clicked, this, &PcbCamPopViewWindow::onPanLeftClicked);
    connect(viewRightBtn, &QPushButton::clicked, this, &PcbCamPopViewWindow::onPanRightClicked);
    connect(zoomInBtn, &QPushButton::clicked, this, &PcbCamPopViewWindow::onZoomInClicked);
    connect(zoomOutBtn, &QPushButton::clicked, this, &PcbCamPopViewWindow::onZoomOutClicked);

}

PcbCamPopViewWindow::~PcbCamPopViewWindow()
{

}

void PcbCamPopViewWindow::setSourceRect(const QRectF &iSourceRect)
{
    Q_D(PcbCamPopViewWindow);
    d->sourceRect = iSourceRect;
}

QRectF PcbCamPopViewWindow::sourceRect() const
{
    Q_D(const PcbCamPopViewWindow);
    return d->sourceRect;
}

QRect PcbCamPopViewWindow::viewRect() const
{
    Q_D(const PcbCamPopViewWindow);
    QRect rect = d->imageLabel->rect();
    rect.moveTo(d->imageLabel->mapToGlobal(rect.topLeft()));
    return rect;
}

void PcbCamPopViewWindow::refresh()
{
    Q_D(PcbCamPopViewWindow);
    QRectF sceneRect = d->sourceRect;
    QRect imgRect(QPoint(0, 0), d->imageLabel->size());

    auto disprect = d->canvas->orientMatrix().mapRect(sceneRect.normalized()).normalized();
    qreal scale = qMin(double(imgRect.width())/disprect.width(),
                       double(imgRect.height())/disprect.height());
    QTransform mat = d->canvas->orientMatrix() * QTransform(scale, 0, 0, -scale, 0, 0);
    disprect = mat.mapRect(sceneRect.normalized());
    mat = mat * QTransform(1, 0, 0, 1, imgRect.center().x() - disprect.center().x(), imgRect.center().y() - disprect.center().y());

    QPixmap pix = d->canvas->render(mat, d->imageLabel->rect().size());
    d->imageLabel->setPixmap(pix);
}

void PcbCamPopViewWindow::resizeEvent(QResizeEvent *event)
{
    emit geometryChanged();
    this->refresh();
}

void PcbCamPopViewWindow::closeEvent(QCloseEvent *event)
{
    emit aboutToClose();
    QWidget::closeEvent(event);
}

void PcbCamPopViewWindow::mouseReleaseEvent(QMouseEvent *event)
{
    Q_D(PcbCamPopViewWindow);
    QApplication::restoreOverrideCursor();
    event->ignore();
    d->isLeftPressDown = false;
}

void PcbCamPopViewWindow::mousePressEvent(QMouseEvent *event)
{
    Q_D(PcbCamPopViewWindow);
    switch(event->button()) {
    case Qt::LeftButton:
        d->isLeftPressDown = true;
        if(d->mouseRegion != PcbCamPopViewWindowPrivate::NONE) {
            this->mouseGrabber();
        } else {
            d->dragPosition = event->globalPos() - this->frameGeometry().topLeft();
        }
        break;
    default:
        QFrame::mousePressEvent(event);
    }
}

void PcbCamPopViewWindow::mouseMoveEvent(QMouseEvent *event)
{
    Q_D(PcbCamPopViewWindow);
    QPoint gloPoint = event->globalPos();
    QRect rect = this->rect();
    QPoint tl = mapToGlobal(rect.topLeft());
    QPoint rb = mapToGlobal(rect.bottomRight());

    if(!d->isLeftPressDown) {
        d->region(gloPoint);
    } else {

        if(d->mouseRegion != PcbCamPopViewWindowPrivate::NONE) {
            QRect rMove(tl, rb);

            switch(d->mouseRegion) {
            case PcbCamPopViewWindowPrivate::LEFT:
                if(rb.x() - gloPoint.x() <= this->minimumWidth())
                    rMove.setX(tl.x());
                else
                    rMove.setX(gloPoint.x());
                break;
            case PcbCamPopViewWindowPrivate::RIGHT:
                rMove.setWidth(gloPoint.x() - tl.x());
                break;
            case PcbCamPopViewWindowPrivate::UP:
                if(rb.y() - gloPoint.y() <= this->minimumHeight())
                    rMove.setY(tl.y());
                else
                    rMove.setY(gloPoint.y());
                break;
            case PcbCamPopViewWindowPrivate::DOWN:
                rMove.setHeight(gloPoint.y() - tl.y());
                break;
            case PcbCamPopViewWindowPrivate::LEFTTOP:
                if(rb.x() - gloPoint.x() <= this->minimumWidth())
                    rMove.setX(tl.x());
                else
                    rMove.setX(gloPoint.x());
                if(rb.y() - gloPoint.y() <= this->minimumHeight())
                    rMove.setY(tl.y());
                else
                    rMove.setY(gloPoint.y());
                break;
            case PcbCamPopViewWindowPrivate::RIGHTTOP:
                rMove.setWidth(gloPoint.x() - tl.x());
                rMove.setY(gloPoint.y());
                break;
            case PcbCamPopViewWindowPrivate::LEFTBOTTOM:
                rMove.setX(gloPoint.x());
                rMove.setHeight(gloPoint.y() - tl.y());
                break;
            case PcbCamPopViewWindowPrivate::RIGHTBOTTOM:
                rMove.setWidth(gloPoint.x() - tl.x());
                rMove.setHeight(gloPoint.y() - tl.y());
                break;
            default:
                break;
            }
            this->setGeometry(rMove);
        } else {
            move(event->globalPos() - d->dragPosition);
            event->accept();
        }
    }
    QFrame::mouseMoveEvent(event);
}

void PcbCamPopViewWindow::moveEvent(QMoveEvent *event)
{
    emit geometryChanged();
    QWidget::moveEvent(event);
}


void PcbCamPopViewWindow::onPanUpClicked()
{
    Q_D(PcbCamPopViewWindow);
    d->sourceRect.translate(0, (double(d->sourceRect.height()) * 0.1));
    emit geometryChanged();
    this->refresh();
}

void PcbCamPopViewWindow::onPanDownClicked()
{
    Q_D(PcbCamPopViewWindow);
    d->sourceRect.translate(0, (-double(d->sourceRect.height()) * 0.1));
    emit geometryChanged();
    this->refresh();
}

void PcbCamPopViewWindow::onPanLeftClicked()
{
    Q_D(PcbCamPopViewWindow);
    d->sourceRect.translate((-double(d->sourceRect.width()) * 0.1), 0);
    emit geometryChanged();
    this->refresh();
}

void PcbCamPopViewWindow::onPanRightClicked()
{
    Q_D(PcbCamPopViewWindow);
    d->sourceRect.translate((double(d->sourceRect.width()) * 0.1), 0);
    emit geometryChanged();
    this->refresh();
}

void PcbCamPopViewWindow::onZoomInClicked()
{
    Q_D(PcbCamPopViewWindow);
    QPointF pc = d->sourceRect.center();
    qreal scale = 1.0/1.2;
    qreal w = double(d->sourceRect.width()) * scale;
    qreal h = double(d->sourceRect.height()) * scale;
    d->sourceRect = QRectF(pc.x() - w/2.0, pc.y()-h/2.0, w, h);
    emit geometryChanged();
    this->refresh();
}

void PcbCamPopViewWindow::onZoomOutClicked()
{
    Q_D(PcbCamPopViewWindow);
    QPointF pc = d->sourceRect.center();
    qreal scale = 1.2;
    qreal w = double(d->sourceRect.width()) * scale;
    qreal h = double(d->sourceRect.height()) * scale;
    d->sourceRect = QRectF(pc.x() - w/2.0, pc.y()-h/2.0, w, h);
    emit geometryChanged();
    this->refresh();
}
