classdef(Hidden,Sealed) ModelFactory < handle
    %MODELFACTORY Factory class for producing model objects in the
    %econModeler app
    
    %Copyright 2017-2018 The MathWorks, Inc. 
    
    properties
        Session
    end
    
    methods(Access = ?internal.EconModeler.econModelerSession)
        function this = ModelFactory(session)
            this.Session = session;
        end
        
        function determineModelType(this,~,e)
            import internal.EconModeler.Enumerations.ModelTypes
            try
                switch e.RequestedModel
                    case ModelTypes.AR
                        createARModel(this,e.Options);
                    case ModelTypes.MA
                        createMAModel(this,e.Options);
                    case ModelTypes.ARMA
                        createARMAModel(this,e.Options);
                    case ModelTypes.ARIMA
                        createARIMAModel(this,e.Options);
                    case ModelTypes.SARIMA
                        createSARIMAModel(this,e.Options);
                    case ModelTypes.ARIMAX
                        createARIMAXModel(this,e.Options);
                    case ModelTypes.SARIMAX
                        createSARIMAXModel(this,e.Options);
                    case ModelTypes.GARCH
                        createGARCHModel(this,e.Options);
                    case ModelTypes.EGARCH
                        createEGARCHModel(this,e.Options);
                    case ModelTypes.GJR
                        createGJRModel(this,e.Options);
                    case ModelTypes.MLR
                        createMLRModel(this,e.Options);
                    case ModelTypes.REGARIMA
                        createRegARIMAModel(this,e.Options);
                    case ModelTypes.VAR
                        createVARModel(this,e.Options);
                    case ModelTypes.VARX
                        createVARXModel(this,e.Options);
                    case ModelTypes.VECComponent
                        createVECComponentModel(this,e.Options);
                    case ModelTypes.VECImpact
                        createVECImpactModel(this,e.Options);
                end
            catch Me
                rethrow(Me);
            end
        end
    end
     
    methods(Access = private)        
        function createARModel(this,parameters)
            import internal.EconModeler.EconComponents.Models.ARModel
            import internal.EconModeler.EventData.ModelEventData
            
            selection = parameters.TimeSeries;
            arLags = parameters.ARLags;
            constant = parameters.Constant;
            distribution = parameters.Distribution;
            tab = parameters.Tab;
            
            newModel = ARModel(this.Session,selection,tab,constant,arLags,distribution);
             
            notify(this.Session,'NewModelCreated',ModelEventData(newModel));
        end
        
        function createMAModel(this,parameters)
            import internal.EconModeler.EconComponents.Models.MAModel
            import internal.EconModeler.EventData.ModelEventData
            
            selection = parameters.TimeSeries;
            maLags = parameters.MALags;
            constant = parameters.Constant;
            distribution = parameters.Distribution;
            tab = parameters.Tab;
            
            newModel = MAModel(this.Session,selection,tab,constant,maLags,distribution);
            
            notify(this.Session,'NewModelCreated',ModelEventData(newModel));
        end
        
        function createARMAModel(this,parameters)
            import internal.EconModeler.EconComponents.Models.ARMAModel
            import internal.EconModeler.EventData.ModelEventData
            
            selection = parameters.TimeSeries;
            arLags = parameters.ARLags;
            maLags = parameters.MALags;
            constant = parameters.Constant;
            distribution = parameters.Distribution;
            tab = parameters.Tab;
            
            newModel = ARMAModel(this.Session,selection,tab,constant,arLags,maLags,distribution);
            
            notify(this.Session,'NewModelCreated',ModelEventData(newModel));
        end
        
        function createARIMAModel(this,parameters)
            import internal.EconModeler.EconComponents.Models.ARIMAModel
            import internal.EconModeler.EventData.ModelEventData
            
            selection = parameters.TimeSeries;
            arLags = parameters.ARLags;
            d = parameters.D;
            maLags = parameters.MALags;
            constant = parameters.Constant;
            distribution = parameters.Distribution;
            tab = parameters.Tab;
            
            newModel = ARIMAModel(this.Session,selection,tab,constant,arLags,d,maLags,distribution);
            
            notify(this.Session,'NewModelCreated',ModelEventData(newModel));
        end 
        
        function createSARIMAModel(this,parameters)
            import internal.EconModeler.EconComponents.Models.SARIMAModel
            import internal.EconModeler.EventData.ModelEventData
            
            selection = parameters.TimeSeries;
            arLags = parameters.ARLags;
            d = parameters.D;
            maLags = parameters.MALags;
            sarLags = parameters.SARLags;
            seasonality = parameters.Seasonality;
            smaLags = parameters.SMALags;
            constant = parameters.Constant;
            distribution = parameters.Distribution;
            tab = parameters.Tab;
            
            newModel = SARIMAModel(this.Session,selection,tab,constant,arLags,d,maLags,...
                sarLags,seasonality,smaLags,distribution);
            
            notify(this.Session,'NewModelCreated',ModelEventData(newModel));
        end
        
         function createARIMAXModel(this,parameters)
            import internal.EconModeler.EconComponents.Models.ARIMAXModel
            import internal.EconModeler.EventData.ModelEventData
            
            selection = parameters.TimeSeries;
            arLags = parameters.ARLags;
            d = parameters.D;
            maLags = parameters.MALags;
            exogenous = parameters.Exogenous;
            tab = parameters.Tab;
            
            covariates = [];
            for n = 1:length(exogenous)
                covariates = [covariates; this.Session.getTimeSeries(exogenous{n})]; %#ok<AGROW>
            end
           
            constant = parameters.Constant;
            distribution = parameters.Distribution;
            
            newModel = ARIMAXModel(this.Session,selection,tab,constant,arLags,d,maLags,...
                covariates,distribution);
            
            notify(this.Session,'NewModelCreated',ModelEventData(newModel));
        end
        
        function createSARIMAXModel(this,parameters)
            import internal.EconModeler.EconComponents.Models.SARIMAXModel
            import internal.EconModeler.EventData.ModelEventData
            
            selection = parameters.TimeSeries;
            arLags = parameters.ARLags;
            d = parameters.D;
            maLags = parameters.MALags;
            sarLags = parameters.SARLags;
            seasonality = parameters.Seasonality;
            smaLags = parameters.SMALags;
            exogenous = parameters.Exogenous;
            tab = parameters.Tab;
            
            covariates = [];
            for n = 1:length(exogenous)
                covariates = [covariates; this.Session.getTimeSeries(exogenous{n})]; %#ok<AGROW>
            end
           
            constant = parameters.Constant;
            distribution = parameters.Distribution;
            
            newModel = SARIMAXModel(this.Session,selection,tab,constant,arLags,d,maLags,...
                sarLags,seasonality,smaLags,covariates,distribution);
            
            notify(this.Session,'NewModelCreated',ModelEventData(newModel));
        end
            
            
        
        function createGARCHModel(this,parameters)
            import internal.EconModeler.EconComponents.Models.GARCHModel
            import internal.EconModeler.EventData.ModelEventData
            
            selection = parameters.TimeSeries;
            garchLags = parameters.GARCHLags;
            archLags = parameters.ARCHLags;
            offset = parameters.Offset;
            distribution = parameters.Distribution;
            tab = parameters.Tab;
            
            newModel = GARCHModel(this.Session,selection,tab,garchLags,archLags,...
                offset,distribution);
            
            notify(this.Session,'NewModelCreated',ModelEventData(newModel));
        end
        
        function createEGARCHModel(this,parameters)
            import internal.EconModeler.EconComponents.Models.EGARCHModel
            import internal.EconModeler.EventData.ModelEventData
            
            selection = parameters.TimeSeries;
            garchLags = parameters.GARCHLags;
            archLags = parameters.ARCHLags;
            leverageLags = parameters.LeverageLags;
            offset = parameters.Offset;
            distribution = parameters.Distribution;
            tab = parameters.Tab;
            
            newModel = EGARCHModel(this.Session,selection,tab,garchLags,archLags,...
                leverageLags,offset,distribution);
            
            notify(this.Session,'NewModelCreated',ModelEventData(newModel));
        end
        
        function createGJRModel(this,parameters)
            import internal.EconModeler.EconComponents.Models.GJRModel
            import internal.EconModeler.EventData.ModelEventData
            
            selection = parameters.TimeSeries;
            garchLags = parameters.GARCHLags;
            archLags = parameters.ARCHLags;
            leverageLags = parameters.LeverageLags;
            offset = parameters.Offset;
            distribution = parameters.Distribution;
            tab = parameters.Tab;
            
            newModel = GJRModel(this.Session,selection,tab,garchLags,archLags,...
                leverageLags,offset,distribution);
            
            notify(this.Session,'NewModelCreated',ModelEventData(newModel));
        end
        
        function createMLRModel(this,parameters)
            import internal.EconModeler.EconComponents.Models.MLRModel
            import internal.EconModeler.EventData.ModelEventData
            
            selection = parameters.TimeSeries;
            exogenous = parameters.Exogenous;
            
            covariates = [];
            for n = 1:length(exogenous)
                covariates = [covariates; this.Session.getTimeSeries(exogenous{n})]; %#ok<AGROW>
            end
            
            constant = parameters.Constant;
            tab = parameters.Tab;
            
            newModel = MLRModel(this.Session,selection,tab,constant,covariates);
            
            notify(this.Session,'NewModelCreated',ModelEventData(newModel));
        end
        
        function createRegARIMAModel(this,parameters)
            import internal.EconModeler.EconComponents.Models.RegARIMAModel
            import internal.EconModeler.EventData.ModelEventData
            
            selection = parameters.TimeSeries;
            arLags = parameters.ARLags;
            maLags = parameters.MALags;
            exogenous = parameters.Exogenous;            
            tab = parameters.Tab;
            
            covariates = [];
            for n = 1:length(exogenous)
                covariates = [covariates; this.Session.getTimeSeries(exogenous{n})]; %#ok<AGROW>
            end
           
            constant = parameters.Constant;
            distribution = parameters.Distribution;
            
            newModel = RegARIMAModel(this.Session,selection,tab,constant,arLags,maLags,...
                covariates,distribution);
            
            notify(this.Session,'NewModelCreated',ModelEventData(newModel));
        end
        
        function createVARModel(this,parameters)
            import internal.EconModeler.EconComponents.Models.VARModel
            import internal.EconModeler.EventData.ModelEventData
            
            selection = parameters.TimeSeries;
            ar = parameters.AR;
            constant = parameters.Constant;
            trend = parameters.Trend;
            tab = parameters.Tab;
            arOrder = parameters.AROrder;
            arVector = parameters.ARVector;
            
            newModel = VARModel(this.Session,selection,tab,ar,constant,trend,arOrder,arVector);
            
            notify(this.Session,'NewModelCreated',ModelEventData(newModel));
        end

        function createVARXModel(this,parameters)
            import internal.EconModeler.EconComponents.Models.VARXModel
            import internal.EconModeler.EventData.ModelEventData

            selection = parameters.TimeSeries;
            ar = parameters.AR;
            constant = parameters.Constant;
            trend = parameters.Trend;
            arOrder = parameters.AROrder;
            arVector = parameters.ARVector;

            exogenous = parameters.Exogenous;   
            covariates = [];
            for n = 1:length(exogenous)
                covariates = [covariates; this.Session.getTimeSeries(exogenous{n})]; %#ok<AGROW>
            end
            tab = parameters.Tab;

            newModel = VARXModel(this.Session,selection,tab,...
                ar,constant,trend,arOrder,arVector,covariates);

            notify(this.Session,'NewModelCreated',ModelEventData(newModel));
        end

        function createVECComponentModel(this,parameters)
            import internal.EconModeler.EconComponents.Models.VECComponentModel
            import internal.EconModeler.EventData.ModelEventData

            selection = parameters.TimeSeries;
            form = parameters.Form;
            rank = parameters.Rank;
            adjustment = parameters.Adjustment;
            cointegration = parameters.Cointegration;
            shortRun = parameters.ShortRun;
            shortRunOrder = parameters.ShortRunOrder;
            shortRunVector = parameters.ShortRunVector;
            tab = parameters.Tab;

            newModel = VECComponentModel(this.Session,selection,form,rank,...
                adjustment,cointegration,shortRun,shortRunOrder,shortRunVector,tab);

            notify(this.Session,'NewModelCreated',ModelEventData(newModel));
        end

        function createVECImpactModel(this,parameters)
            import internal.EconModeler.EconComponents.Models.VECImpactModel
            import internal.EconModeler.EventData.ModelEventData

            selection = parameters.TimeSeries;
            form = parameters.Form;
            impact = parameters.Impact;
            shortRun = parameters.ShortRun;
            shortRunOrder = parameters.ShortRunOrder;
            shortRunVector = parameters.ShortRunVector;
            tab = parameters.Tab;

            newModel = VECImpactModel(this.Session,selection,form,...
                impact,shortRun,shortRunOrder,shortRunVector,tab);

            notify(this.Session,'NewModelCreated',ModelEventData(newModel));
        end

    end
end

