% This function is part of the NMSM Pipeline, see file for full license.
%
% This function calculates the terminal constraint for design optimization
%
% (struct, struct, struct) -> (Array of number)
% Returns terminal constraint
function event = calcDesignOptimizationTerminalConstraint(values, ...
    modeledValues, params)
event = [];
for i = 1:length(params.terminal)
    constraintTerm = params.terminal{i};
    if constraintTerm.isEnabled
        switch constraintTerm.type
            case "state_position_periodicity"
                event = cat(2, event, ...
                    calcStatePositionPeriodicity(values.statePositions, ...
                    params.coordinateNames, ...
                    constraintTerm.coordinate));
            case "state_velocity_periodicity"
                event = cat(2, event, ...
                    calcStateVelocityPeriodicity(values.stateVelocities, ...
                    params.coordinateNames, ...
                    constraintTerm.coordinate));
            case "root_segment_residual_load_periodicity"
                event = cat(2, event, ...
                    calcRootSegmentResidualsPeriodicity(... 
                    modeledValues.inverseDynamicMoments, ...
                    params.inverseDynamicMomentLabels, ...
                    constraintTerm.load));    
            case "external_force_periodicity"
                event = cat(2, event, ...
                    calcExternalForcesPeriodicity(... 
                    modeledValues.groundReactionsLab.forces, ...
                    params.contactSurfaces, ...
                    constraintTerm.force));  
            case "external_moment_periodicity"
                event = cat(2, event, ...
                    calcExternalMomentsPeriodicity(... 
                    modeledValues.groundReactionsLab.moments, ...
                    params.contactSurfaces, ...
                    constraintTerm.moment));  
            case "final_state_position"
                event = cat(2, event, ...
                    calcFinalStatePosition(values.statePositions, ...
                    params.coordinateNames, ...
                    constraintTerm));  
            case "final_state_velocity"
                event = cat(2, event, ...
                    calcFinalStateVelocity(values.stateVelocities, ...
                    params.coordinateNames, ...
                    constraintTerm)); 
            case "final_point_position"
                event = cat(2, event, ...
                    calcFinalPointPosition(params, values, ...
                    constraintTerm));      
            case "final_point_velocity"
                event = cat(2, event, ...
                    calcFinalPointVelocity(params, values, ...
                    constraintTerm));
            otherwise
                throw(MException('', ['Constraint term type ' ...
                    constraintTerm.type ' does not exist for this tool.']))    
        end
    end
end
end