function [outputModel, phi] = calculateModelOutput(obj,input,output)
% CALCULATEMODELOUTPUT Simulate the output of the model given an input sequence
%
% [outputModel, phi] = calculateModelOutput(obj,input,output)
%
% OUTPUTS:
%   outputModel:    N x q    Matrix of model outputs
%   phi:            N x M    Matrix of phi (validity function values)
%
% INPUTS:
%   obj:            obj      Class-object
%   input:          N x p    Data matrix containing physical inputs
%   output:         N x q    (optional) Data matrix containing physical outputs. These are only needed for dynamic systems

% LMNtool - Local Model Network Toolbox
% Tobias Ebert, 24-April-2012
% Institute of Mechanics & Automatic Control, University of Siegen, Germany
% Copyright (c) 2012 by Prof. Dr.-Ing. Oliver Nelles

if ~exist('input','var') && ~exist('output','var')
    % if no input and output is given use the precalculated regressors. This
    % if-else combinations saves a lot of computation time in training!
    xRegressor = obj.xRegressor;
    zRegressor = obj.zRegressor;
else
    if ~isempty(obj.scaleInput)
        % if input should be scaled
        input = obj.scaleInput.scale(input);
    end
    
    if ~isempty(obj.scaleOutput) && exist('output','var')
        % if output should be scaled
        output = obj.scaleOutput.scale(output);
    elseif ~exist('output','var')
        % if input is given, but no output
        output = [];
    end
    xRegressor = obj.data2xRegressor(input,output);
    zRegressor = obj.data2zRegressor(input,output);
end


if obj.kStepPrediction <= 1 % Static model or dynamic model with one-step-ahead prediction
    
    if ~exist('input','var') && ~exist('output','var') && isprop(obj,'phi') && ~isempty(obj.phi)
        % if there is no input given (only happens in training)
        phi = obj.phi(:,obj.leafModels);
    else
        % if there is no given phi, calculate it
        phi = obj.calculatePhi(zRegressor,obj.leafModels);
    end
    
    % get the local model parameter from the obj into cell arrays
    % localParameter = arrayfun(@(cobj) cobj.parameter,obj.localModels(obj.leafModels),'UniformOutput',false);
    localParameter = {obj.localModels(obj.leafModels).parameter};
    
    
    %calculate the output
    outputModel = obj.calcYhat(xRegressor,phi,localParameter);
    
else % Dynamic model parallel simulation
    
    [outputModel,phi] = obj.simulateParallel(xRegressor,zRegressor);
    
end

if  ~isempty(obj.scaleOutput)
   % always unscale output 
    outputModel = obj.scaleOutput.unscale(outputModel);
end

end


