/*****************************************************************************
 * $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 "ActionTabPresenter.h"

#include <Application.h> // for getting action families and component class names
#include <Action.h>

#include "QtPropertyFieldEditor.h"
#include "TextFieldEditor.h"
#include "CamiTKPropertyFieldEditor.h"
#include "ExpandableFieldEditor.h"
#include "CamiTKPropertyListFieldEditor.h"
#include "ListFieldEditor.h"
#include "FileFieldEditor.h"

// -------------------- constructor --------------------
ActionTabPresenter::ActionTabPresenter(CamiTKExtensionModelPresenter* presenter, VariantDataModel& dataModel, QWidget* parent) : ExtensionTypeTabPresenter(camitk::ExtensionManager::ACTION, presenter, dataModel, parent) {
    QWidget* tab = new QWidget(parent);

    setWidget(tab);
    setWidgetResizable(true);
    setStyleSheet("QScrollArea { background-color: palette(button); }");

    actionTabLayout = new QGridLayout(tab);
    actionTabLayout->setContentsMargins(0, 0, 0, 0);

    FieldEditor* fieldEditor;

    QtPropertyFieldEditor* qtPropertyFieldEditor = new QtPropertyFieldEditor(presenter, dataModel["name"], "name", "Name of the action (cannot be modified interactively).", "New Action Name");
    qtPropertyFieldEditor->setReadOnly(true);
    qtPropertyFieldEditor->appendRowTo(actionTabLayout);

    fieldEditor = new TextFieldEditor(presenter, dataModel["description"], "description", "<p>This text is used to describe the action (also used for tooltip and whatsThis).</p><p>This can be any <a href='https://doc.qt.io/qt-6/richtext-html-subset.html'>rich text</a> formatted string.</p>");
    fieldEditor->appendRowTo(actionTabLayout);

    qtPropertyFieldEditor = new QtPropertyFieldEditor(presenter, dataModel["componentClass"], "Component", R"(<p>Component class name: this is the type (i.e. name of the class) of the component used in input of this action . Usually choose between:</p>
    <ul>
        <li><tt>ImageComponent</tt> for image data</li>
        <li><tt>MeshComponent</tt> for 3D objects</li>
    </ul>
    <p>You can also enter the name of any other valid Component class.<br/>
        Leave it empty if your action does not require any input data.</p>)", "");
    QStringList allComponentClassNameEnum;
    for (auto a : camitk::Application::getActions()) {
        allComponentClassNameEnum.append(a->getComponentClassName());
    }
    QStringList componentClassNameEnum = buildEnum(allComponentClassNameEnum);
    // remove the empty one as the editable line edit can be used to leave it empty (otherwise there are two empty lines)
    componentClassNameEnum.removeOne("");
    qtPropertyFieldEditor->setEnumValues(componentClassNameEnum);
    qtPropertyFieldEditor->setEditableEnum(true);
    qtPropertyFieldEditor->setRegExp(R"(\b[a-zA-Z_]\w*\b)"); // C++ class name constraint
    qtPropertyFieldEditor->setPlaceHolderText("Choose a Component class name from the list, leave it empty if none are required, or enter a custom Component class here.");
    qtPropertyFieldEditor->appendRowTo(actionTabLayout);

    QWidget* expandableWidget = new QWidget();
    QGridLayout* expandableGridLayout = new QGridLayout(expandableWidget);
    VariantDataModel& classification = dataModel["classification"];
    if (!classification.isValid()) {
        // if classification does not exists, creates an empty map so that adding family and tags are valid actions
        dataModel["classification"] = VariantDataModel(QVariantMap());
    }
    qtPropertyFieldEditor = new QtPropertyFieldEditor(presenter, dataModel["classification"]["family"], "Action family", R"(<p>A family groups different actions that are linked to the same user activity. It is useful to specify a family to help the user find the right action.</p><p>When right clicking on a component, the action of the same families are grouped under the same menu item. Here is a list of frequently used action family:</p>
        <ul>
            <li>Segmentation</li>
            <li>Image Processing</li>
            <li>Mesh Processing</li>
            <li>Display</li>
            <li>Image Acquisition</li>
        </ul>
        <p>Feel free to create a new family for your actions, choose the new family name wisely.)", "");
    QStringList allFamilyNames;
    for (auto a : camitk::Application::getActions()) {
        allFamilyNames.append(a->getFamily());
    }
    QStringList familyEnum = buildEnum(allFamilyNames);
    familyEnum.removeOne("");
    qtPropertyFieldEditor->setEnumValues(familyEnum);
    qtPropertyFieldEditor->setEditableEnum(true);
    qtPropertyFieldEditor->setPlaceHolderText("Choose a family from the list or enter a custom family name here.");
    qtPropertyFieldEditor->appendRowTo(expandableGridLayout);

    ListFieldEditor* listFieldEditor = new ListFieldEditor(presenter, dataModel["classification"]["tags"], "tags", "<p>Tags is a list of keywords about the action. They are useful to help the user to find the right action.</p><p>Press <tt>Insert</tt> or <tt>+</tt> to insert new tags, <tt>Delete</tt> to remove the current tag, and click on a tag to edit the text.");
    listFieldEditor->appendRowTo(expandableGridLayout);
    ExpandableFieldEditor* advancedEditor = new ExpandableFieldEditor(presenter, expandableWidget, dataModel, "Classification", false, true);
    advancedEditor->appendRowTo(actionTabLayout);

    //-- properties
    expandableWidget = new QWidget();
    expandableGridLayout = new QGridLayout(expandableWidget);
    expandableGridLayout->setContentsMargins(0, 0, 0, 0);
    VariantDataModel& parameters = dataModel["parameters"];
    if (!parameters.isValid()) {
        // if parameters does not exists, creates an empty list so that adding new parameters is a valid action
        dataModel["parameters"] = VariantDataModel(QVariantList());
    }
    for (unsigned int index = 0; index < parameters.size(); index++) {
        fieldEditor = new CamiTKPropertyFieldEditor(presenter, parameters[index], parameters[index]["name"], "Action parameter.");
        fieldEditor->appendRowTo(expandableGridLayout, true);
    }
    CamiTKPropertyListFieldEditor* advancedParamEditor = new CamiTKPropertyListFieldEditor(presenter, expandableWidget, parameters, "Parameters", false, true);
    advancedParamEditor->appendRowTo(actionTabLayout);

}
