/*****************************************************************************
 * $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$
 ****************************************************************************/

// -- Application ObjectController stuff
#include "PropertyUI.h"
using namespace camitk;

// -- QT stuff
#include <QTextEdit>
#include <QComboBox>
#include <QVector3D>

PropertyUI::PropertyUI(QWidget* parent) : QWidget(parent) {

    // create the UI
    theController = new ObjectController(this, ObjectController::TREE);

    QPushButton* applyButton = new QPushButton(tr("&Apply"));
    connect(applyButton, SIGNAL(clicked()), theController, SLOT(apply()));
    connect(applyButton, SIGNAL(clicked()), this, SLOT(print()));
    QPushButton* resetButton = new QPushButton(tr("&Revert"));
    connect(resetButton, SIGNAL(clicked()), theController, SLOT(revert()));
    connect(resetButton, SIGNAL(clicked()), this, SLOT(print()));
    QPushButton* printButton = new QPushButton(tr("&Print"));
    connect(printButton, SIGNAL(clicked()), this, SLOT(print()));
    auto* comboBox = new QComboBox;
    comboBox->addItem("Tree");
    comboBox->addItem("GroupBox");
    comboBox->addItem("Button");
    connect(comboBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(changeViewMode(QString)));

    // plug the console
    console = new QTextEdit();
    console->setReadOnly(true);

    QHBoxLayout* buttonLayout = new QHBoxLayout;
    buttonLayout->addWidget(applyButton);
    buttonLayout->addWidget(resetButton);
    buttonLayout->addWidget(printButton);
    buttonLayout->addWidget(comboBox);

    QVBoxLayout* mainLayout = new QVBoxLayout;
    mainLayout->addWidget(theController);
    mainLayout->addLayout(buttonLayout);
    mainLayout->addWidget(console);

    setLayout(mainLayout);
}

void PropertyUI::setPropertyObject(QObject* object) {
    theController->setObject(object);
    print(); // to see the initial values
}

void PropertyUI::changeViewMode(QString mode) {
    if (mode == "Tree") {
        theController->setViewMode(ObjectController::TREE);
    }
    else if (mode == "GroupBox") {
        theController->setViewMode(ObjectController::GROUPBOX);
    }
    else if (mode == "Button") {
        theController->setViewMode(ObjectController::BUTTON);
    }
}

QString PropertyUI::propertyToString(QString name, QVariant value) {
    QString valueInString = "<li>" + name + ": ";
    switch (value.userType()) {
        case QMetaType::QVector3D: {
            QVector3D val = value.value<QVector3D>();
            valueInString +=  "QVector3D(" + QString::number(val.x()) + "," + QString::number(val.y()) + "," + QString::number(val.z())  + ")";
        }
        break;
        case QMetaType::QColor:
            valueInString += "<font color=" + value.toString() + ">" + value.toString() + "</font>";
            break;
        default:
            valueInString += value.toString();
            break;
    }

    valueInString += "</li>";
    return valueInString;
}

void PropertyUI::print() {
    QString toString;
    toString += "Static Properties:<ul>";
    const QMetaObject* metaObject = theController->object()->metaObject();
    // check all static properties
    for (int idx = metaObject->propertyOffset(); idx < metaObject->propertyCount(); idx++) {
        QMetaProperty metaProperty = metaObject->property(idx);
        QString propName = metaProperty.name();
        QVariant propValue = metaProperty.read(theController->object());
        // special case for QVariantMap
        if (metaProperty.userType() == QMetaType::QVariantMap) {
            toString += propertyToString(propName, "group of properties");
            toString += "<ul>";
            // print the subproperties
            QMapIterator<QString, QVariant> it(propValue.toMap());
            while (it.hasNext()) {
                it.next();
                toString += propertyToString(it.key(), it.value());
            }
            toString += "</ul>";
        }
        else {
            toString += propertyToString(propName, propValue);
        }
    }

    toString += "</ul>";

    // check all dynamic properties
    toString += "<hr/>Dynamic Properties:<ul>";
    QList<QByteArray> dynProp = theController->object()->dynamicPropertyNames();

    for (int idx = 0; idx < dynProp.size(); ++idx) {
        toString += propertyToString(QString(dynProp.at(idx)), theController->object()->property(dynProp.at(idx)));
    }
    toString += "</ul>";

    // display
    console->setHtml(toString);
}
