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

// CamiTK includes
#include <Component.h>
#include <ImageComponent.h>
#include <Application.h>
#include <TransformationManager.h>
#include <Property.h>
#include <ActionWidget.h>
#include <Log.h>

using namespace camitk;

// -------------------- init --------------------
void SetFrameFrom::init() {
}

// -------------------- process --------------------
Action::ApplyStatus SetFrameFrom::process() {

    int sourceIndex = getParameterValue("Source Component").value<int>();
    Component* sourceComponent = componentList[sourceIndex];

    if (Application::isAlive(sourceComponent)) {
        // Iterate over all targets
        for (Component* target : getTargets()) {
            // Ignore the sourceComponent and SingleImageComponents that might have been selected along their parent ImageComponent
            if (target != sourceComponent) {
                if (dynamic_cast<ImageComponent*>(sourceComponent) != nullptr && dynamic_cast<ImageComponent*>(target)
                        && getParameterValue("Main Frame Only").value<int>() == 0) {
                    // If both target and sourceComponent are images, and we only want to set a common main frame
                    target->setFrame(TransformationManager::getFrameOfReferenceOwnership(sourceComponent->getFrame()));
                }
                else {
                    // All other cases
                    target->setFrameFrom(sourceComponent);
                }
            }
        }
    }
    // We might have unused Frames now, cleanup !
    TransformationManager::cleanupFramesAndTransformations();
    refreshApplication();
    return SUCCESS;
}

// -------------------- targetDefined --------------------
void SetFrameFrom::targetDefined() {
    // Update the list of of Components
    QStringList componentListNames;
    componentList = Application::getTopLevelComponents();
    for (Component* comp : componentList) {
        componentListNames << comp->getName();
    }
    Property* sourceComponentProperty = getProperty("Source Component");
    sourceComponentProperty->setAttribute("enumNames", componentListNames);

    // select the first value in the combobox
    setProperty("Source Component", 0);
}

// -------------------- parameterChanged --------------------
void SetFrameFrom::parameterChanged(QString parameterName) {
    if (parameterName == "Source Component") {
        int sourceIndex = getParameterValue("Source Component").value<int>();
        if (sourceIndex < componentList.size() && Application::isAlive(componentList[sourceIndex])) {
            Property* useAllProperty = getProperty("Main Frame Only");
            if (dynamic_cast<ImageComponent*>(componentList[sourceIndex]) != nullptr) {
                // We have an image for the source component, useAll has no meaning -> read only
                setParameterValue("Main Frame Only", 0); // Use main frame only
                useAllProperty->setReadOnly(true);
            }
            else {
                setParameterValue("Main Frame Only", 1); // Use all frames
                useAllProperty->setReadOnly(false);
            }
            // We changed the readonly property, we should update the widget
            // But generating an event in an event segfaults, even with blockSignal
            // dynamic_cast<camitk::ActionWidget*>(Action::getWidget())->update();
        }
    }
}

