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

#include <Property.h>
#include <Component.h>
#include <Log.h>

#include <QString>
#include <QDate>
#include <QTextStream>
#include <QVector3D>

using namespace camitk;


// --------------- Constructor -------------------
AddDynamicProperty::AddDynamicProperty(ActionExtension* extension) : Action(extension) {
    // Setting name, description and input component
    setName("Add Dynamic Property");
    setDescription("Add a dynamic property to the currently selected component.");
    setComponentClassName("Component");

    // Setting classification family and tags
    setFamily("Tutorial");
    addTag("Dynamic Property");
    addTag("Component");

    // Setting the action's parameters
    addParameter(new Property("Name", "", "Name of the new property to add to the selection", ""));
    addParameter(new Property("Initial Value", "", "Initial value of the property", ""));
    addParameter(new Property("Description", "Dynamically <b>added</b> <i>property!</i>", "Description of the property", ""));
    addParameter(new Property("Unit", "", "Unit of Measurement of the property", ""));
    currentType = BOOL;

    // notify this action every time the user change something
    setAutoUpdateProperties(true);
}

// --------------- destructor -------------------
AddDynamicProperty::~AddDynamicProperty() {
    // Do not do anything yet.
    // Delete stuff if you create stuff
    // (except if you use smart pointers of course !!)
}

// --------------- apply -------------------
Action::ApplyStatus AddDynamicProperty::apply() {
    QString description = getParameterValue("Description").toString();
    QString unit = getParameterValue("Unit").toString();
    QString name = getParameterValue("Name").toByteArray().constData();
    for (Component* comp : getTargets()) {

        if (comp->getProperty(name)) { // the property already exits, modify its value
            switch (currentType) {
                case AddDynamicProperty::INT:
                    comp->setProperty(name.toStdString().c_str(), QVariant(getParameterValue("Initial Value").toInt()));
                    break;
                case AddDynamicProperty::CHAR:
                    comp->setProperty(name.toStdString().c_str(), QVariant(getParameterValue("Initial Value").toChar()));
                    break;
                case AddDynamicProperty::BOOL:
                    comp->setProperty(name.toStdString().c_str(), QVariant(getParameterValue("Initial Value").toBool()));
                    break;
                case AddDynamicProperty::FLOAT:
                    comp->setProperty(name.toStdString().c_str(), QVariant(getParameterValue("Initial Value").toDouble()));
                    break;
                case AddDynamicProperty::DOUBLE:
                    comp->setProperty(name.toStdString().c_str(), QVariant(getParameterValue("Initial Value").toDouble()));
                    break;
                case AddDynamicProperty::QDATE:
                    comp->setProperty(name.toStdString().c_str(), QVariant(getParameterValue("Initial Value").toDate()));
                    break;
                case AddDynamicProperty::QTIME:
                    comp->setProperty(name.toStdString().c_str(), QVariant(getParameterValue("Initial Value").toTime()));
                    break;
                case AddDynamicProperty::QCOLOR:
                    comp->setProperty(name.toStdString().c_str(), getParameterValue("Initial Value").value<QColor>());
                    break;
                case AddDynamicProperty::QPOINT:
                    comp->setProperty(name.toStdString().c_str(), getParameterValue("Initial Value").value<QPoint>());
                    break;
                case AddDynamicProperty::QPOINTF:
                    comp->setProperty(name.toStdString().c_str(), getParameterValue("Initial Value").value<QPointF>());
                    break;
                case AddDynamicProperty::QVECTOR3D:
                    comp->setProperty(name.toStdString().c_str(), getParameterValue("Initial Value").value<QVector3D>());
                    break;
                case AddDynamicProperty::QSTRING:
                default:
                    //setProperty("Initial Value","QString(\"Hello New Property\")");
                    comp->setProperty(name.toStdString().c_str(), getParameterValue("Initial Value").toString());
                    break;
            }
        }
        else {   // the property doesn't exit yet, add it!
            switch (currentType) {
                case AddDynamicProperty::INT:
                    comp->addProperty(new Property(name, QVariant(getParameterValue("Initial Value").toInt()), description, unit));
                    break;
                case AddDynamicProperty::CHAR:
                    comp->addProperty(new Property(name, QVariant(getParameterValue("Initial Value").toChar()), description, unit));
                    break;
                case AddDynamicProperty::BOOL:
                    comp->addProperty(new Property(name, QVariant(getParameterValue("Initial Value").toBool()), description, unit));
                    break;
                case AddDynamicProperty::FLOAT:
                    comp->addProperty(new Property(name, QVariant(getParameterValue("Initial Value").toDouble()), description, unit));
                    break;
                case AddDynamicProperty::DOUBLE:
                    comp->addProperty(new Property(name, QVariant(getParameterValue("Initial Value").toDouble()), description, unit));
                    break;
                case AddDynamicProperty::QDATE:
                    comp->addProperty(new Property(name, QVariant(getParameterValue("Initial Value").toDate()), description, unit));
                    break;
                case AddDynamicProperty::QTIME:
                    comp->addProperty(new Property(name, QVariant(getParameterValue("Initial Value").toTime()), description, unit));
                    break;
                case AddDynamicProperty::QCOLOR:
                    comp->addProperty(new Property(name, getParameterValue("Initial Value").value<QColor>(), description, unit));
                    break;
                case AddDynamicProperty::QPOINT:
                    comp->addProperty(new Property(name, getParameterValue("Initial Value").value<QPoint>(), description, unit));
                    break;
                case AddDynamicProperty::QPOINTF:
                    comp->addProperty(new Property(name, getParameterValue("Initial Value").value<QPointF>(), description, unit));
                    break;
                case AddDynamicProperty::QVECTOR3D:
                    comp->addProperty(new Property(name, getParameterValue("Initial Value").value<QVector3D>(), description, unit));
                    break;
                case AddDynamicProperty::QSTRING:
                default:
                    //setProperty("Initial Value","QString(\"Hello New Property\")");
                    comp->addProperty(new Property(name, getParameterValue("Initial Value").toString(), description, unit));
                    break;
            }
        }

        // refresh viewers
        comp->refresh();
    }
    return SUCCESS;
}

// --------------- getPropertyType -------------------
AddDynamicProperty::PropertyType AddDynamicProperty::getPropertyType() {
    return currentType;
}

// --------------- setPropertyType -------------------
void AddDynamicProperty::setPropertyType(AddDynamicProperty::PropertyType propertyType) {
    currentType = propertyType;

    switch (currentType) {
        case AddDynamicProperty::INT:
            setParameterValue("Initial Value", "0");
            break;
        case AddDynamicProperty::CHAR:
            setParameterValue("Initial Value", "'a'");
            break;
        case AddDynamicProperty::BOOL:
            setParameterValue("Initial Value", "false");
            break;
        case AddDynamicProperty::DOUBLE:
        case AddDynamicProperty::FLOAT:
            setParameterValue("Initial Value", "0.0");
            break;
        case AddDynamicProperty::QDATE: {
            QDate today = QDate::currentDate();
            QString defValue;
            QTextStream in(&defValue);
            in << "QDate(" << today.year() << ", " << today.month() << ", " << today.day() << ")";
            setParameterValue("Initial Value", defValue);
            break;
        }
        case AddDynamicProperty::QTIME: {
            QTime now = QTime::currentTime();
            QString defValue;
            QTextStream in(&defValue);
            in << "QTime(" << now.hour() << ", " << now.minute() << ", " << now.second() << ")";
            setParameterValue("Initial Value", defValue);
            break;
        }
        case AddDynamicProperty::QCOLOR:
            setParameterValue("Initial Value", "QColor(255, 255, 255, 255)");
            break;
        case AddDynamicProperty::QPOINT:
            setParameterValue("Initial Value", "QPoint(0, 0)");
            break;
        case AddDynamicProperty::QPOINTF:
            setParameterValue("Initial Value", "QPointF(0.0, 0.0)");
            break;
        case AddDynamicProperty::QVECTOR3D:
            setParameterValue("Initial Value", "QVector3D(0.0, 0.0, 0.0)");
            break;
        case AddDynamicProperty::QSTRING:
        default:
            setParameterValue("Initial Value", "QString(\"Hello New Property\")");
            break;
    }
}



