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

// CamiTK includes
#include <Application.h>
#include <Component.h>
#include <ActionWidget.h>
#include <InteractiveGeometryViewer.h>
#include <TransformationExplorer.h>
#include <Log.h>

#include <algorithm>

using namespace camitk;

// -------------------- init --------------------
void ShowFrame::init() {
    currentFrame = nullptr;
    frameComponent = nullptr;
    // No need to show Apply/Revert button, this action is done in realtime when the parameter changes
    setDefaultWidgetButtonVisibility(false);
    TransformationExplorer* transfoExplorer = dynamic_cast<TransformationExplorer*>(Application::getViewer("Transformation Explorer"));
    if (transfoExplorer != nullptr) {
        connect(transfoExplorer, &TransformationExplorer::currentFrameChanged, this, &ShowFrame::setCurrentFrame);
    }
}

// -------------------- process --------------------
Action::ApplyStatus ShowFrame::process() {
    return SUCCESS;
}

// -------------------- targetDefined --------------------
void ShowFrame::targetDefined() {
}

// -------------------- parameterChanged --------------------
void ShowFrame::parameterChanged(QString parameterName) {
    if (parameterName == "Show Frame") {
        // TODO: Show the currentFrame, even if no Component is present
        if (currentFrame != nullptr) {
            if (frameComponent != nullptr) {
                frameComponent->setFrameVisibility("3D Viewer", getParameterValue("Show Frame").toBool());
                // force refresh of the 3D viewer only
                InteractiveGeometryViewer* default3DViewer = dynamic_cast<InteractiveGeometryViewer*>(Application::getViewer("3D Viewer"));
                if (default3DViewer != nullptr) {
                    default3DViewer->refresh();
                    default3DViewer->getRendererWidget()->resetCamera();
                }
            }
            else {
                CAMITK_WARNING("This frame does not belong to a Component, it cannot be shown/hidden.")
            }
        }
    }
}

// -------------------- setCurrentFrame --------------------
void ShowFrame::setCurrentFrame(const FrameOfReference* frame) {
    currentFrame = frame;
    if (frame != nullptr) {
        // Try to find a Component using it:
        // Try to find a component that uses this frame
        auto frameComponentIterator = std::ranges::find_if(Application::getAllComponents(), [frame](Component * c) {
            return c->getFrame() == frame;
        });
        if (frameComponentIterator != Application::getAllComponents().cend()) {
            frameComponent = *frameComponentIterator;
        }
        else {
            frameComponent = nullptr;
        }
        if (frameComponent != nullptr) {
            setParameterValue("Show Frame", frameComponent->getFrameVisibility("3D Viewer"));
            dynamic_cast<camitk::ActionWidget*>(Action::getWidget())->update();
        }
    }
}
