/***************************** LICENSE START ***********************************

 Copyright 2014 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#include "MvQRequestPanelWidget.h"

#include <QApplication>
#include <QDebug>
#include <QDropEvent>
#include <QGridLayout>
#include <QPainter>
#include <QPalette>
#include <QTimer>

#include "MvQIconMimeData.h"
#include "MvQTheme.h"

#include "IconClass.h"
#include "IconObject.h"

QBrush MvQRequestPanelWidget::bgBrushLeft_ = Qt::red;
QBrush MvQRequestPanelWidget::bgBrushRight_;
QPen MvQRequestPanelWidget::linePenHorizontal_;
QPen MvQRequestPanelWidget::linePenVertical_;
QPen MvQRequestPanelWidget::linePenReset_;

MvQRequestPanelWidget::MvQRequestPanelWidget(const std::vector<std::string>& cls, QWidget* parent) :
    QWidget(parent),
    classes_(cls),
    delayedRepaintScheduled_(false)
{
    if (bgBrushLeft_.color() == Qt::red) {
        bgBrushLeft_       = MvQTheme::brush("editor", "line_item_brush_left");
        bgBrushRight_      = MvQTheme::brush("editor", "line_item_brush_right");
        linePenHorizontal_ = QPen(MvQTheme::colour("editor", "line_item_pen_horizontal"));
        linePenVertical_   = QPen(MvQTheme::colour("editor", "line_item_pen_vertical"));
        linePenReset_      = MvQTheme::colour("editor", "line_item_pen_reset");
    }
    setAcceptDrops(true);
}

//We paint the grid lines to the widget holding the gridlayout. The problem is that
//it is not called all the time when the gridlayout changes (items are hidden/shown)!
void MvQRequestPanelWidget::paintEvent(QPaintEvent* event)
{
    QPainter painter(this);

    //paint bg
    QPalette pal = palette();
    painter.fillRect(0, 0, this->width(), this->height(), pal.color(QPalette::Window));

    QGridLayout* grid = static_cast<QGridLayout*>(layout());
    if (!grid) {
        QWidget::paintEvent(event);
        return;
    }

    painter.setPen(linePenHorizontal_);

    //The spacing in the gridlayout
    int spacingV = grid->verticalSpacing();
    int spacingH = grid->horizontalSpacing();

    int firstY   = 0;
    int lastY    = 0;
    int bgSplitX = 0;
    int rowNum   = grid->rowCount();

    //Find the border between the left and right hand side
    for (int i = 0; i < rowNum; i++) {
        //At position 3 we have the widget in the row
        if (QLayoutItem* item = grid->itemAtPosition(i, 3)) {
            QWidget* w = item->widget();
            if (w && w->isVisible()) {
                QRect r = item->geometry();
                int h   = r.height() + spacingV;
                int y   = r.y() - spacingV / 2;

                if (firstY == 0)
                    firstY = y;

                lastY = y + h;

                if (bgSplitX == 0)
                    bgSplitX = r.x() - spacingH / 2;
            }
        }
    }

    if (firstY == 0 || lastY == 0 || bgSplitX == 0)
        return;

    //fill the left side
    painter.fillRect(0, firstY, bgSplitX, lastY - firstY + 1, bgBrushLeft_);

    //fill the right side
    painter.fillRect(bgSplitX, firstY,
                     this->width() - bgSplitX, lastY - firstY + 1, bgBrushRight_);

    //Draw the horizontal lines
    for (int i = 0; i < rowNum; i++) {
        //At position 3 we have the widget in the row
        if (QLayoutItem* item = grid->itemAtPosition(i, 3)) {
            QWidget* w = item->widget();
            if (w && w->isVisible()) {
                QRect r = item->geometry();

                //int h=r.height()+spacingV;
                int y = r.y() - spacingV / 2;

                //Horizontal line
                painter.drawLine(0, y, this->width(), y);
            }
        }
    }


    //The last horizontal line
    painter.drawLine(0, lastY, this->width(), lastY);

    //The vertical separator line between the left and right hand side
    painter.setPen(linePenVertical_);
    painter.drawLine(bgSplitX, firstY, bgSplitX, lastY);

    //Frame
    painter.setPen(Qt::black);
    painter.drawRect(0, 0, this->width(), this->height());
}

void MvQRequestPanelWidget::delayedForceRepaint()
{
    if (!delayedRepaintScheduled_) {
        QTimer::singleShot(1, this, SLOT(forceRepaint()));
        delayedRepaintScheduled_ = true;
    }
}

void MvQRequestPanelWidget::forceRepaint()
{
    repaint();
    qApp->processEvents();
    delayedRepaintScheduled_ = false;
}

bool MvQRequestPanelWidget::isAccepted(const IconClass& kind) const
{
    // if the user drops an icon into the icon editor then we should
    // always accept it and try to merge the requests
    return true;
}

//===========================
// Drop from the new Desktop
//===========================

void MvQRequestPanelWidget::dragEnterEvent(QDragEnterEvent* event)
{
    if ((event->proposedAction() == Qt::CopyAction ||
         event->proposedAction() == Qt::MoveAction)) {
        event->accept();
    }
}

void MvQRequestPanelWidget::dragMoveEvent(QDragMoveEvent* event)
{
    if ((event->proposedAction() == Qt::CopyAction ||
         event->proposedAction() == Qt::MoveAction)) {
        event->accept();
    }
}

void MvQRequestPanelWidget::dropEvent(QDropEvent* event)
{
    if (event->proposedAction() != Qt::CopyAction &&
        event->proposedAction() != Qt::MoveAction) {
        event->ignore();
        return;
    }

    if (event->mimeData()->hasFormat("metview/icon")) {
        const MvQIconMimeData* mimeData = qobject_cast<const MvQIconMimeData*>(event->mimeData());

        if (!mimeData) {
            event->ignore();
            return;
        }

        IconObject* obj = mimeData->dragObject();

        if (!obj || !isAccepted(obj->iconClass())) {
            event->ignore();
            return;
        }

        emit iconDropped(obj);

        event->accept();
        return;
    }

    event->ignore();
}
