/*****************************************************************************
 * $CAMITK_LICENCE_BEGIN$
 *
 * CamiTK - Computer Assisted Medical Intervention ToolKit
 * (c) 2001-2025 Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, 38000 Grenoble, France
 *
 * Visit http://camitk.imag.fr for more information
 *
 * This file is part of CamiTK.
 *
 * CamiTK is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * CamiTK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with CamiTK.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $CAMITK_LICENCE_END$
 ****************************************************************************/

#include "ListFieldEditor.h"

#include <QListWidget>
#include <QKeyEvent>
#include <QPushButton>

// -------------------- Constructor --------------------
ListFieldEditor::ListFieldEditor(CamiTKExtensionModelPresenter* presenter, VariantDataModel& dataModel, const QString& name, const QString& description) : FieldEditor(presenter, dataModel, name, description) {
}

// -------------------- getWidget --------------------
QWidget* ListFieldEditor::getWidget() {
    if (myWidget == nullptr) {
        QWidget* listFieldWidget = new QWidget();
        QVBoxLayout* mainLayout = new QVBoxLayout(listFieldWidget);

        // create the list widget
        listWidget = new QListWidget();
        listWidget->setAlternatingRowColors(true);

        for (auto item : dataModel.getValue().toList()) {
            listWidget->addItem(item.toString());
        }
        // the activated item should be editable
        connect(listWidget, &QListWidget::itemActivated, this, [ this ](QListWidgetItem * item) {
            if (item) {
                item->setFlags(item->flags() | Qt::ItemIsEditable);
                listWidget->editItem(item);
            }
        });
        // update model when the user change the item value
        connect(listWidget, &QListWidget::itemChanged, this, [ this ](QListWidgetItem * item) {
            if (item) {
                updateModel();
            }
        });
        listWidget->setStyleSheet(R"(QListWidget::item:selected { border: 1px dashed; color: palette(text);})");
        listWidget->setWhatsThis(description);
        listWidget->setToolTip(description);

        // Set the height of the list widget to have only three lines
        QListWidgetItem* tempItem = nullptr;
        if (listWidget->count() == 0) {
            // (need to create a temporary item to get the size hint if dataModel is empty)
            tempItem = new QListWidgetItem(listWidget);
        }
        int itemHeight = listWidget->sizeHintForRow(0);
        listWidget->setFixedHeight(itemHeight * 3);
        delete tempItem;

        mainLayout->addWidget(listWidget);

        // Label of the dataModel (remove the "s" if plural)
        QString itemTypeName = name.at(0).toUpper() + name.mid(1, name.size() - ((name.endsWith('s')) ? 2 : 1));

        // create +/- buttons
        QHBoxLayout* addRemoveButtonsLayout = new QHBoxLayout();

        QPushButton* minusButton = new QPushButton("Remove " + itemTypeName);
        minusButton->setFixedHeight(minusButton->fontMetrics().height());
        minusButton->setToolTip("Remove currently selected item");
        minusButton->setWhatsThis("Remove currently selected item");
        connect(minusButton, &QPushButton::clicked, this, [ this ]() {
            delete listWidget->currentItem();
            updateModel();
        });
        addRemoveButtonsLayout->addWidget(minusButton);

        QPushButton* plusButton = new QPushButton("Add " + itemTypeName);
        plusButton->setFixedHeight(plusButton->fontMetrics().height());
        plusButton->setToolTip("Add a new item");
        plusButton->setWhatsThis("Add a new item");
        connect(plusButton, &QPushButton::clicked, this, [ =, this ]() {
            // Label of the dataModel (remove the "s" if plural)
            QString newName = "New " + itemTypeName;
            listWidget->addItem(newName);
            updateModel();
        });
        addRemoveButtonsLayout->addWidget(plusButton);

        mainLayout->addLayout(addRemoveButtonsLayout);

        // compact space
        QList<QWidget*> widgetToCompact = { listFieldWidget, listWidget, minusButton, plusButton};
        for (auto w : widgetToCompact) {
            w->setContentsMargins(0, 0, 0, 0);
            w->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
        }
        QList<QLayout*> layoutToCompact = { mainLayout, addRemoveButtonsLayout};
        for (auto l : layoutToCompact) {
            l->setContentsMargins(0, 0, 0, 0);
            l->setSpacing(0);
            l->setContentsMargins(0, 0, 0, 0);
        }

        myWidget = listFieldWidget;
    }
    return myWidget;
}

// -------------------- updateModel --------------------
void ListFieldEditor::updateModel() {
    // update the model
    QStringList values;
    for (int row = 0; row < listWidget->count(); row++) {
        QListWidgetItem* item = listWidget->item(row);
        values << item->text();
    }
    dataModel = values;
    presenter->modelUpdated();
}

