/**
 *
 * @file src/interface/viteqtreewidget.cpp
 *
 * @copyright 2008-2024 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
 *                      Univ. Bordeaux. All rights reserved.
 *
 * @author Camille Ordronneau
 * @author Johnny Jazeix
 * @author Augustin Degomme
 *
 * @date 2024-07-17
 */
#include <QDropEvent>
#include <QDragMoveEvent>
#include <QDragEnterEvent>
#include <QMimeData>
#include <QList>
#include "viteqtreewidget.hpp"
#include "stdio.h"

viteQTreeWidget::viteQTreeWidget(QWidget *parent) :
    QTreeWidget(parent) {
}

viteQTreeWidget::~viteQTreeWidget() = default;

void viteQTreeWidget::dropEvent(QDropEvent *e) {

    // we want to avoid to destroy the hierarchy of the trace, so let's only move containers near a container with the same parent

    // QTreeWidgetItem* item= itemAt(event->pos());//get the item where we want to move
    // printf("drop %s to %s!\n", );

    //   const QPoint pos = e->pos();
    QTreeWidgetItem *target = itemAt(e->pos());

    if (target == nullptr) {
        e->ignore();
        return;
    }

    bool do_move = true;

    // this is used to determine if the target is itself a child

    for (const QTreeWidgetItem *item: qAsConst(selected_items)) {

        // if target and item don't share the same parent...
        if (target->parent() != item->parent()) {
            // ...then don't allow the move
            do_move = false;
            break;
        }

        if (target == item) {
            // ...do nothing
            do_move = false;
            break;
        }
    }

    if (!do_move)
        e->setDropAction(Qt::IgnoreAction);
    else {
        // QTreeWidget::dropEvent(e);
        int index = 0;
        if (target->parent())
            index = target->parent()->indexOfChild(target);
        else
            index = indexOfTopLevelItem(target);

        int modifier = 0;

        int initial_count = 0;
        if (target->parent())
            initial_count = target->parent()->childCount();
        else
            initial_count = topLevelItemCount();

        // we want to insert below the pointed event
        for (QTreeWidgetItem *item: qAsConst(selected_items)) {
            // remove all items from their parent

            if (item->parent()) {
                if (item->parent()->indexOfChild(item) < index)
                    modifier++;
                item->parent()->removeChild(item);
            }
            else {
                if (indexOfTopLevelItem(item) < index)
                    modifier++;
                takeTopLevelItem(indexOfTopLevelItem(item));
            }
        }
        // insert them again in the right position and order

        if (target->parent())
            index = target->parent()->indexOfChild(target);
        else
            index = indexOfTopLevelItem(target);

        int max = 0;
        if (target->parent()) {
            if (index + modifier > target->parent()->childCount()) {
                max = target->parent()->childCount();
                for (QTreeWidgetItem *item: qAsConst(selected_items)) {
                    target->parent()->insertChild(max, item);
                    max++;
                }
            }
            else {
                max = index + modifier;
                target->parent()->insertChildren(max, selected_items);
            }
        }
        else {
            if (index + modifier > topLevelItemCount()) {
                max = topLevelItemCount();
                for (QTreeWidgetItem *item: qAsConst(selected_items)) {
                    insertTopLevelItem(max, item);
                    max++;
                }
            }
            else {
                max = index + modifier;
                insertTopLevelItems(max, selected_items);
            }
        }

        int count = 0;
        if (target->parent())
            count = target->parent()->childCount();
        else
            count = topLevelItemCount();

        if (count != initial_count) {
            // prevent loss of elements if insertions failed (can happen sometimes)
            // try to reinsert all elements at the end
            for (QTreeWidgetItem *item: qAsConst(selected_items)) {
                if (target->parent())
                    target->parent()->insertChild(target->parent()->childCount(), item);
                else
                    insertTopLevelItem(topLevelItemCount(), item);
            }
        }
        e->setDropAction(Qt::TargetMoveAction);
    }

    e->accept();
    selected_items.clear();
}

void viteQTreeWidget::dragEnterEvent(QDragEnterEvent *event) {
    selected_items = selectedItems();
    if (event->source() == this) {
        event->setDropAction(Qt::MoveAction);
        event->accept();
    }
    else
        event->acceptProposedAction();
}

void viteQTreeWidget::dragMoveEvent(QDragMoveEvent *e) {
    e->accept();
}

#if QT_VERSION >= 0x060000
QMimeData *viteQTreeWidget::mimeData(const QList<QTreeWidgetItem *> &) const {
#else
QMimeData *viteQTreeWidget::mimeData(const QList<QTreeWidgetItem *>) const {
#endif
    return new QMimeData;
}

bool viteQTreeWidget::dropMimeData(QTreeWidgetItem *, int, const QMimeData *, Qt::DropAction) {
    return true;
}

Qt::DropActions viteQTreeWidget::supportedDropActions() const {
    return Qt::CopyAction | Qt::MoveAction;
}

#include "moc_viteqtreewidget.cpp"
