/*****************************************************************************
 * $CAMITK_LICENCE_BEGIN$
 *
 * CamiTK - Computer Assisted Medical Intervention ToolKit
 * (c) 2001-2024 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 "ActionWidget.h"
#include "Action.h"
#include "ObjectController.h"
#include "Component.h"
#include <Application.h>
#include <MainWindow.h>

namespace camitk {

// -------------------- constructor --------------------
ActionWidget::ActionWidget(Action* action): QFrame() {
    myAction = action;

    // create the property editor tab itself
    setObjectName(myAction->getName());

    auto* widgetLayout = new QVBoxLayout;

    // Action's name and icon
    QLabel* iconPicture = new QLabel;
    iconPicture->setPixmap(myAction->getIcon());
    actionNameLabel = new QLabel("<b>" + myAction->getName() + "</b>");
    auto* nameLayout = new QHBoxLayout;
    nameLayout->addWidget(iconPicture);
    nameLayout->addWidget(actionNameLabel);

    widgetLayout->addLayout(nameLayout);

    // get the proper text height
    actionNameLabel->adjustSize();
    // fix the icon height
    iconPicture->setFixedSize(actionNameLabel->height(), actionNameLabel->height());
    iconPicture->setScaledContents(true);

    // create the tabs
    QTabWidget* widgetTabs = new QTabWidget;

    // Action description presentation
    descriptionTextEdit = new QTextEdit(myAction->getDescription());
    descriptionTextEdit->setFrameStyle(QFrame::NoFrame | QFrame::Plain);
    descriptionTextEdit->setReadOnly(true);
    // more discrete background color for read only textedit
    QPalette readOnlyPalette = descriptionTextEdit->palette();
    QColor windowBackgroundColor = readOnlyPalette.color(QPalette::Window);
    readOnlyPalette.setColor(QPalette::Base, windowBackgroundColor);
    descriptionTextEdit->setPalette(readOnlyPalette);
    auto* descriptionLabelScrollArea = new QScrollArea();
    descriptionLabelScrollArea->setWidget(descriptionTextEdit);
    descriptionLabelScrollArea->setWidgetResizable(true);
    descriptionLabelScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);

    widgetTabs->addTab(descriptionLabelScrollArea, tr("Description"));

    // Targets list display
    auto* targetLabelScrollArea = new QScrollArea();
    targetLabelScrollArea->setWidgetResizable(true);
    targetLabel = new QLabel(getTargetLabel());
    targetLabel->setAlignment(Qt::AlignTop);
    targetLabel->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
    targetLabel->setLineWidth(3);
    targetLabel->setWordWrap(true);
    targetLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
    targetLabel->setScaledContents(true);
    targetLabelScrollArea->setWidget(targetLabel);
    widgetTabs->addTab(targetLabelScrollArea, tr("Targets"));

    // first the property editor
    objectController = new ObjectController(this, ObjectController::BUTTON);
    widgetTabs->addTab(objectController, tr("Parameters"));
    widgetTabs->setCurrentIndex(2);

    widgetLayout->addWidget(widgetTabs);

    // then the buttons
    buttonFrame = new QFrame();
    auto* buttonLayout = new QHBoxLayout;
    QPushButton* applyButton = new QPushButton(tr("Apply"));
    buttonLayout->addWidget(applyButton);
    QPushButton* revertButton = new QPushButton(tr("Revert"));
    buttonLayout->addWidget(revertButton);
    buttonFrame->setLayout(buttonLayout);

    widgetLayout->addWidget(buttonFrame);

    // connect the buttons
    QObject::connect(applyButton, SIGNAL(clicked()), objectController, SLOT(apply()));
    // from http://doc.trolltech.com/4.7/signalsandslots.html
    // "If several slots are connected to one signal, the slots will be executed one after the other,
    // in the order they have been connected, when the signal is emitted."
    // it means that here when the user click on apply, it will first update the properties
    // and then call the apply() method
    QObject::connect(applyButton, SIGNAL(clicked()), myAction, SLOT(applyAndRegister()));
    QObject::connect(revertButton, SIGNAL(clicked()), objectController, SLOT(revert()));

    // Now tell the ObjectController that this Action itself is the one to manage
    objectController->setObject(myAction);

    setLayout(widgetLayout);
}

// -------------------- destructor --------------------
ActionWidget::~ActionWidget() {
    // TODO delete
}

// -------------------- setButtonVisibility --------------------
void ActionWidget::setButtonVisibility(bool visible) {
    buttonFrame->setVisible(visible);
}

// -------------------- setNameVisibility --------------------
void ActionWidget::setNameVisibility(bool visible) {
    this->actionNameLabel->setVisible(visible);
}

// -------------------- setDescriptionVisibility --------------------
void ActionWidget::setDescriptionVisibility(bool visible) {
    this->descriptionTextEdit->setVisible(visible);
}

// -------------------- update --------------------
void ActionWidget::update() {
    // force update
    objectController->setObject(nullptr);
    objectController->setObject(myAction);
    targetLabel->setText(getTargetLabel());
}

// -------------------- getTargetLabel --------------------
QString ActionWidget::getTargetLabel() {
    QString targetNames = "<p>Currently Selected Targets:</p><ul>";

    foreach (Component* comp, myAction->getTargets()) {
        targetNames += "<li> " + comp->getName() + "<i> (" + comp->metaObject()->className() + ") </i>" + "</li>";
    }

    targetNames += "</ul>";
    return targetNames;
}

// -------------------- setAutoUpdateProperty --------------------
void ActionWidget::setAutoUpdateProperty(bool autoUpdate) {
    objectController->setAutoUpdateProperty(autoUpdate);
}

}
