$licenseComment$
#include "$upperCamelCase(name)$.h"

//
// Generated source for action "$title(name)$"
// $date()$ - $time()$
//

// CamiTK includes
#include <Property.h>
#include <Log.h>
#include <ActionWidget.h>

@if@ $userIncludesInImplementation$
// Additional includes
$userIncludesInImplementation$
@endif@

@if@ $itkFilters$
// Itk includes
#include <itkVTKImageToImageFilter.h>
#include <itkImageToVTKImageFilter.h>
#include <ItkProgressObserver.h>
@endif@

@if@ $implementationIncludes$
// includes for specific types
$implementationIncludes$
@endif@

@if@ $componentClass$
// This action process $componentClass$, include is required
#include <$componentClass$.h>
@endif@

using namespace camitk;

// ------------------- Constructor -------------------
$upperCamelCase(name)$::$upperCamelCase(name)$(ActionExtension* extension) : Action(extension) {
    // Setting name, description and input component
    setName("$title(name)$");
    setDescription(R"($description$)");
    setComponentClassName("$componentClass$");

    // Setting classification family and tags
    setFamily("$classification.family$");
    @for@ $tag$ in $classification.tags$
    addTag("$tag$");
    @endfor@

    // block event management
    initializationPending = true;

    @if@ $parameters$
    // Setting the action's parameters
    Property* param;
    @endif@
    
    @for@ $p$ in $parameters$
    @if@ contains($p.enumValues$)
    param = new Property("$title(p.name)$", (int) $p.defaultValue$, tr("$p.description$"), "$p.unit$");
    @else@
    param = new Property("$title(p.name)$", ($p.type$) $p.defaultValue$, tr("$p.description$"), "$p.unit$");
    @endif@
    @if@ $p.group$
    param->setGroupName("$p.group$");
    @endif@
    @if@ contains($p.minimum$)
    param->setAttribute("minimum", (double) $p.minimum$);
    @endif@
    @if@ $p.maximum$
    param->setAttribute("maximum", (double) $p.maximum$);
    @endif@
    @if@ $p.decimals$
    param->setAttribute("decimals", $p.decimals$);
    @endif@
    @if@ $p.singleStep$
    param->setAttribute("singleStep", $p.singleStep$);
    @endif@
    @if@ $p.regExp$
    param->setAttribute("regExp", QRegularExpression("$p.regExp$"));
    @endif@
    @if@ $p.readOnly$
    param->setReadOnly(true);
    @endif@
    @if@ contains($p.enumValues$)
    // Set the enum type
    param->setEnumTypeName("$upperCamelCase(p.name)$Enum");
    // Populate the enum values
    QStringList $lowerCamelCase(p.name)$EnumValues;    
    @subfor@ $enumVal$ in $p.enumValues$
    $lowerCamelCase(p.name)$EnumValues.append("$enumVal$");
    @endsubfor@
    param->setAttribute("enumNames", $lowerCamelCase(p.name)$EnumValues);
    @endif@
    addParameter(param);
    @endfor@

    // call user-defined init()
    init();

    // immediately take the property changes into account
    setAutoUpdateProperties(true);

    // initialization is finish, all events are unblocked
    initializationPending = false;

    @if@ $notEmbedded$
    setEmbedded(false);
    @endif@
}

// ------------------- getWidget -------------------
QWidget* $upperCamelCase(name)$::getWidget() {
@if@ contains($gui$)
    // $gui$ begin
@endif@
@if@ equals($gui$,"No GUI")
    targetDefined();
    return nullptr;
@endif@
@if@ equals($gui$,"Custom GUI")

    if (actionWidget == nullptr) {
        // first call: check the user defined widget
        actionWidget = getUI();
        if (actionWidget != nullptr) {
            targetDefined();
            return actionWidget;
        }
        else {
            // no user defined UI, use default
            QWidget* defaultWidget = Action::getWidget();
            targetDefined();
            return defaultWidget;            
        }
    }    
    else {
        targetDefined();
        ActionWidget* defaultActionWidget = dynamic_cast<ActionWidget*>(actionWidget);
        if (defaultActionWidget != nullptr) {
            // this is a default action widget, make sure the widget has updated targets
            defaultActionWidget->update();
        }
        return actionWidget;
    }
@endif@
@if@ equals($gui$,"Default Action GUI")
    // just use default behaviour
    bool isFirstCall = (actionWidget == nullptr);
    QWidget* defaultWidget = Action::getWidget();
    targetDefined();
    if(isFirstCall){ // Update the default UI after first call to targetDefined
        ActionWidget* defaultActionWidget = dynamic_cast<ActionWidget*>(defaultWidget);
        if (defaultActionWidget != nullptr) {
            // this is a default action widget, make sure the widget has updated targets
            defaultActionWidget->update();
        }
    }
    return defaultWidget;
@endif@
@if@ contains($gui$)
    // $gui$ end
@else@
    // no GUI specified: just use default behaviour
    bool isFirstCall = (actionWidget == nullptr);
    QWidget* defaultWidget = Action::getWidget();
    targetDefined();
    if(isFirstCall){ // Update the default UI after first call to targetDefined
        ActionWidget* defaultActionWidget = dynamic_cast<ActionWidget*>(defaultWidget);
        if (defaultActionWidget != nullptr) {
            // this is a default action widget, make sure the widget has updated targets
            defaultActionWidget->update();
        }
    }
    return defaultWidget;
@endif@
}

// ------------------- apply -------------------
Action::ApplyStatus $upperCamelCase(name)$::apply() {
    // call user-defined process()
    return process();
}


// ---------------------- event ----------------------------
bool $upperCamelCase(name)$::event(QEvent* e) {
    if (e->type() == QEvent::DynamicPropertyChange && !initializationPending) {
        e->accept();
        QDynamicPropertyChangeEvent* changeEvent = dynamic_cast<QDynamicPropertyChangeEvent*>(e);

        if (changeEvent != nullptr) {
            // call user-defined parameterChanged()
            parameterChanged(changeEvent->propertyName());
            return true;
        }
        else {
            return false;
        }
    }

    // this is important to continue the process if the event is a different one
    return QObject::event(e);
}