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

 Copyright 2013 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 *************************************/

#pragma once

#include <QGraphicsItem>
#include <QGraphicsProxyWidget>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QHash>
#include <QPersistentModelIndex>
#include <QTime>
#include <QTimer>

#include "MvQFolderViewBase.h"

#include "IconObject.h"

class QLineEdit;
class MvQActionList;
class MvQIconItem;
class MvQIconFolderView;
class MvQIconMimeData;

class MvQIconItemTimer : public QTimer
{
    Q_OBJECT

public:
    MvQIconItemTimer(MvQIconItem*, QObject* parent = nullptr);
    void setItem(MvQIconItem*);
    void blink();

public slots:
    void slotTimeout();

protected:
    MvQIconItem* item_;
    int cnt_;
    const int maxCnt_;
};


class MvQEditorProxy : public QGraphicsProxyWidget
{
    Q_OBJECT
public:
    MvQEditorProxy(MvQIconItem* item, QGraphicsItem* parent = nullptr);
    QLineEdit* editor();
    MvQIconItem* item();

Q_SIGNALS:
    void finishedEditing();

protected:
    void keyPressEvent(QKeyEvent*) override;

    MvQIconItem* item_;
    QLineEdit* editor_;
};

/*class MvQDropTargetItem : public QGraphicsItem
{
public:
    MvQDropTargetItem(MvQIconItem*,bool);
    QRectF boundingRect() const;
        void paint(QPainter*, const QStyleOptionGraphicsItem *,QWidget*);
    void setTarget(MvQIconItem*,bool);

protected:
    void adjust(bool);

    MvQIconItem* target_;
    QRectF bRect_;
    QString text1_;
    QString text2_;
    int xPadding_;
    int yPadding_;
    int textOffset_;
    QPen bgPen_;
    QBrush bgBrush_;
    QPixmap pix_;
};*/


class MvQIconItem : public QGraphicsItem
{
public:
    MvQIconItem(const QModelIndex& index, MvQFolderItemProperty* itemProp, MvQIconFolderView*, QGraphicsItem* parent = nullptr);
    QRectF boundingRect() const override;
    void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;
    const QPersistentModelIndex& index() const;
    QRect pixmapRect();
    QString text();
    QFont font();
    void adjust();
    bool textContains(QPointF);
    void setDropTarget(bool);
    enum BlinkState
    {
        NoBlink,
        BlinkOn,
        BlinkOff
    };
    void setBlinkState(BlinkState);
    QPointF textPos();

protected:
    void hoverEnterEvent(QGraphicsSceneHoverEvent*) override;
    void hoverLeaveEvent(QGraphicsSceneHoverEvent*) override;

    MvQIconFolderView* view_;
    MvQFolderItemProperty* itemProp_;
    QPersistentModelIndex index_;
    QRectF bRect_;
    QRectF textRect_;
    QRectF iconRect_;
    bool hover_;
    bool dropTarget_;
    BlinkState blinkState_;

    // We make these static members because they are the same for all instances
    static QPen editPen_;
    static QBrush editBrush_;
    static QPen hoverPen_;
    static QBrush hoverBrush_;
    static QPen selectPen_;
    static QBrush selectBrush_;
    static int cornerRad_;
};


class MvQIconFolderView : public QGraphicsView, public MvQFolderViewBase
{
    friend class MvQIconItem;

    Q_OBJECT

public:
    MvQIconFolderView(MvQFolderModel*, MvQActionList*, MvQActionList*, QWidget* parent = nullptr);
    ~MvQIconFolderView() override;

    void toGrid(Desktop::GridSortMode) override;
    static void load(request* r);
    QWidget* concreteWidget() override;
    void doReset() override;

public slots:
    void slotIconSizeChanged();
    void slotObjectArrived(const QModelIndex&);
    void slotObjectRenamed(const QModelIndex&, QString);
    void reset();
    void slotContextMenu(const QPoint&);
    void slotDataChanged(const QModelIndex& from, const QModelIndex& to);
    void slotIconShortCut();
    void slotDefaultShortCut();
    void slotDesktopShortCut();
    void slotRename();

signals:
    void currentFolderChanged(Folder*);
    void folderDoubleCliked(QString);
    void itemEntered(IconObject*);
    void iconCommandRequested(QString, IconObjectH);
    void desktopCommandRequested(QString, QPoint);

protected:
    void attachModel() override;
    void detachModel() override;
    void clearContents();
    void initImportedHalfSizeItems();
    QModelIndex indexAt(QPointF);
    IconObject* iconObjectAt(QPointF);
    MvQIconItem* objectToItem(IconObject* obj);
    MvQIconItem* indexToItem(const QModelIndex& index);
    const QPersistentModelIndex& itemToIndex(QGraphicsItem*);
    IconObject* itemToObject(QGraphicsItem*);
    QRectF itemRect(QGraphicsItem*);
    QRect itemRect(QList<IconObject*>) override;
    QRect itemRect(IconObject*) override;
    QRect pixmapRect(QList<IconObject*>) override;
    QRect pixmapRect(IconObject*) override;
    QModelIndexList selectedIndexes();
    void selectOnlyOneItem(QGraphicsItem*);

    void adjustSceneRect();
    void adjustItems();
    QSize maxItemSize();
    void computeGrid(Desktop::GridSortMode mode = Desktop::GridSortByName);
    void checkPositions();

    bool ignoreItemPositionForCm() override { return false; }

    MvQContextItemSet* cmSet() override;
    void setupShortCut() override;

    bool event(QEvent* event) override;
    void changeEvent(QEvent* event) override;
    void notifyItemEntered(MvQIconItem* item);
    void notifyItemLeft(MvQIconItem* item);
    void mouseDoubleClickEvent(QMouseEvent*) override;
    void keyPressEvent(QKeyEvent*) override;
    void mousePressEvent(QMouseEvent*) override;
    void mouseMoveEvent(QMouseEvent*) override;
    void performDrag(Qt::DropAction, QPoint);
    void dragEnterEvent(QDragEnterEvent*) override;
    void dragMoveEvent(QDragMoveEvent*) override;
    void dragLeaveEvent(QDragLeaveEvent*) override;
    void dropEvent(QDropEvent*) override;
    // void performDrop(Qt::DropAction,IconObject*,QList<IconObject*>,QPoint,QPoint,bool);

    void performDrop(Qt::DropAction dropAction, const MvQIconMimeData* data,
                     QPoint cursorScenePos, bool fromSameView) override;


    void checkDropTarget(QDropEvent*);
    void removeDropTarget();

    void rename(IconObject*) override;
    void edit(QGraphicsItem*);
    void removeEditor();

    QGraphicsItem* findByKey(int);
    QGraphicsItem* findByText(QString);

    void folderChanged() override;
    void blink(const QModelIndex&) override;
    void showIcon(const QModelIndex&) override;
    void iconCommandFromMain(QString name) override;
    void iconCommand(QString, IconObjectH) override;
    void desktopCommand(QString, QPoint) override;

    QPoint prevScrollPos_;
    bool paintEnabled_;
    QString keyboardInput_;
    QTime keyboardInputTime_;

private:
    bool allowMoveAction_;
    bool enterFolders_;
    QPoint mousePos_;
    QPoint startPos_;
    bool canDrag_;
    QMap<QPersistentModelIndex, MvQIconItem*> items_;
    MvQEditorProxy* editor_;
    MvQIconItemTimer* timer_;
    QShortcut* defaultShortCut_;
    MvQActionList* appIconActions_;
    MvQActionList* appDesktopActions_;
};
