/*****************************************************************************
 * $CAMITK_LICENCE_BEGIN$
 *
 * CamiTK - Computer Assisted Medical Intervention ToolKit
 * (c) 2001-2016 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO)
 *
 * 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>

#include <QToolBox>

namespace camitk {

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

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

    QVBoxLayout * widgetLayout = new QVBoxLayout;

    // Action's name and icon
    QLabel * iconPicture = new QLabel;
    iconPicture->setPixmap(myAction->getIcon());
    actionNameLabel = new QLabel("<b>" + myAction->getName() + "</b>");
    QHBoxLayout * 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 surrounding toolbox
    QToolBox * widgetToolbox = new QToolBox;

    // Action description presentation
    QScrollArea * descriptionLabelScrollArea = new QScrollArea();
    descriptionLabelScrollArea->setWidgetResizable(true);
    descriptionLabel = new QLabel(myAction->getDescription());
    descriptionLabel->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
    descriptionLabel->setTextFormat(Qt::RichText);
    descriptionLabel->setLineWidth(3);
    descriptionLabel->setWordWrap(true);
    descriptionLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
    descriptionLabel->setScaledContents(true);
    descriptionLabelScrollArea->setWidget(descriptionLabel);

    // BLACK DOWN-POINTING SMALL TRIANGLE unicode character is U+25BE
    widgetToolbox->addItem(descriptionLabelScrollArea, tr("Description ") + QChar(0xBE,0x25) );

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

    widgetToolbox->addItem(targetLabelScrollArea, tr("Targets ")+ QChar(0xBE,0x25) );

    // first the property editor
    objectController = new ObjectController(this, ObjectController::BUTTON);
    widgetToolbox->addItem(objectController, tr("Parameters ")+ QChar(0xBE,0x25) );
    widgetToolbox->setCurrentWidget(objectController);

    widgetLayout->addWidget(widgetToolbox);


    // then the buttons
    buttonFrame = new QFrame();
    QHBoxLayout * 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->descriptionLabel->setVisible(visible);
}

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

// -------------------- getTargetLabel --------------------
QString ActionWidget::getTargetLabel() {
    QString targetNames = "<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);
}

}
