classdef(Hidden, Sealed) econModelerSession < internal.EconModeler.abstractSession
    %ECONMODELERSESSION Entry class for the econModeler app.
    
    %Copyright 2017-2022 The MathWorks, Inc.
    
    properties(Access = private)
        ToolStripDisplay
        TimeSeriesFactory
        TimeSeriesList
        ModelFactory
        ModelList
        FigureFactory
        TSDataBrowser
        ModelDataBrowser
        PreviewPanel
        DialogFactory
        ContextualTabList
        ReportGenerator
        FullyRendered = false;
    end
    
    properties(Hidden, Transient, SetAccess = private, GetAccess = public)
        App
    end
    
    properties(Hidden, SetAccess = ?internal.EconModeler.ReportGenerator, GetAccess = public)
        LastReport
    end
    
    properties(Hidden, SetAccess = public, GetAccess = ?internal.EconModeler.ReportGenerator)
        PrintReport = true
    end
    
    properties(SetAccess = private,GetAccess = {?internal.EconModeler.Dialogs.ExportDialog,...
            ?internal.EconModeler.Dialogs.ReportDialog})
        SelectedTimeSeries
        SelectedModels
    end
    
    properties(SetAccess = ?internal.EconModeler.Dialogs.ImportDialog,...
            GetAccess = ?internal.EconModeler.EconComponents.AbstractEconComponent)
        OriginalVariable char
        OriginalClass char
    end
    
    properties(SetAccess = ?internal.EconModeler.Dialogs.ImportDialog,...
            GetAccess = {?internal.EconModeler.EconComponents.AbstractEconComponent,... 
            ?internal.EconModeler.ReportGenerator,?internal.EconModeler.Dialogs.ImportDialog})
         TimeBasis
         Limits
    end
    
    properties(SetAccess = ?internal.EconModeler.TimeSeriesFactory,...
            GetAccess = ?internal.EconModeler.ReportGenerator)
        ImportedSeries
    end
    
    
    
    events
        %Events to indicate busy state
        Busy 
        Unbusy
        DialogOpened
        DialogClosed
        
        %Events for user requests
        ImportRequest
        NewTestRequest
        NewTimeSeriesRequest
        EstimateRequest
        NewPlotRequest
        NewTableRequest
        ExportVariableRequest
        GenerateFunctionRequest
        GenerateLiveFunctionRequest
        GenerateReportRequest
        ReportItemsChosen
        
        %New Time Series Events
        DataImported
        NewTimeSeriesCreated
        TimeSeriesRegistered
        
        %New Model Events
        ModelTypeSelection
        NewModelCreated
        ModelRegistered
        
        %Data Browser Events
        TimeSeriesRenameRequest
        TimeSeriesRenameRegistered
        TimeSeriesClearDeleteRequest
        TimeSeriesClearRegistered
        TimeSeriesDataSelectRequest
        TimeSeriesSelected
        ModelRenameRequest
        ModelRenameRegistered
        ModelClearDeleteRequest
        ModelClearRegistered
        SelectionsUpdated
        
        %Figure events
        FigureClosed
        
        %Session clear event
        SessionClear
        
        %App Closed Event (close dialogs)
        AppClosed
        
        
    end
    
    methods(Access = public)
        function this = econModelerSession(varargin)
            %Constructor, create all objects and setup listeners
            options.Tag = 'econModeler';
            options.Title = getString(message('econ:econModeler:AppTitle'));
            options.EnableTheming = true;
            if ispc
                tmpFile = matlab.ui.internal.IconUtils.createTempIconFile('.ico');                     
                matlab.ui.internal.ICOWriter.writeICOFile(tmpFile, [matlabroot, filesep, fullfile('toolbox','econ',...
                    'econGUIs','+internal','+EconModeler','+Icons','EconometricsAppIcon_16.png')]);
                options.Icon = tmpFile;
            else
                options.Icon = [matlabroot, filesep, fullfile('toolbox','econ',...
                    'econGUIs','+internal','+EconModeler','+Icons','EconometricsAppIcon_16.png')];
            end
            this.App = matlab.ui.container.internal.AppContainer(options);
            this.ToolStripDisplay = internal.EconModeler.Toolstrip.ToolStripDisplay(this);
            
            this.DialogFactory = internal.EconModeler.DialogFactory(this);
            this.TimeSeriesList = internal.EconModeler.TimeSeriesList(this);
            this.TimeSeriesFactory = internal.EconModeler.TimeSeriesFactory(this);
            this.ModelFactory = internal.EconModeler.ModelFactory(this);
            this.ModelList = internal.EconModeler.ModelList(this);
            this.FigureFactory = internal.EconModeler.FigureFactory(this);
            %this.FigureList = internal.EconModeler.FigureList(this);
            this.ReportGenerator = internal.EconModeler.ReportGenerator(this);
            
            this.TSDataBrowser = internal.EconModeler.TimeSeriesDataBrowser(this);
            addToAppContainer(this.TSDataBrowser, this.App);
            this.ModelDataBrowser = internal.EconModeler.ModelDataBrowser(this);
            addToAppContainer(this.ModelDataBrowser, this.App);
            this.PreviewPanel = matlab.ui.internal.databrowser.PreviewPanel('previewpanel',getString(message('econ:econModeler:Preview')));
            addToAppContainer(this.PreviewPanel, this.App);
            
            %Connect data browsers with Preview Panel
            monitor(this.PreviewPanel, this.TSDataBrowser);
            monitor(this.PreviewPanel, this.ModelDataBrowser);
                        
            this.ContextualTabList = internal.EconModeler.ContextualTabList(this);
            
            
            %Add the contexts
            this.buildContexts();
            
            addlistener(this,'ImportRequest',@(s,e)checkBeforeImport(this,s,e));
            addlistener(this,'TimeSeriesClearRegistered',@(s,e)cleanupTimeSeriesSelections(this,s,e));
            addlistener(this,'TimeSeriesRenameRegistered',@(s,e)notify(this,'SelectionsUpdated'));
            addlistener(this,'ModelClearRegistered',@(s,e)cleanupModelSelections(this,s,e));
            addlistener(this,'ModelRenameRegistered',@(s,e)notify(this,'SelectionsUpdated'));
            addlistener(this,'GenerateFunctionRequest',@(s,e)generateFunction(this,'plain'));
            addlistener(this,'GenerateLiveFunctionRequest',@(s,e)generateFunction(this,'live'));
            addlistener(this,'SessionClear',@(s,e)clearAllItems(this));
            addlistener(this,'Busy',@(s,e)setWaiting(this,true));
            addlistener(this,'Unbusy',@(s,e)setWaiting(this,false));
            addlistener(this.TSDataBrowser,'DataBrowserSelectionChanged',@(s,e)updateTimeseriesSelections(this,s,e));
            addlistener(this.ModelDataBrowser,'DataBrowserSelectionChanged',@(s,e)updateModelSelections(this,s,e));
            addlistener(this.App, 'PropertyChanged', @(s,e)setupTab(this,s,e));
            addlistener(this.App,'StateChanged',@(s,e)cleanup(this,s,e));
            
            % Confirm requests for closing the app
            this.App.CanCloseFcn = @(s,e)this.closeConfirm; 
            
            % Add Help button to Toolstrip's Quick Access Bar (QAB).
            qabbtn = matlab.ui.internal.toolstrip.qab.QABHelpButton();
            qabbtn.DocName = 'econometricModeler'; % input to doc() command
            add(this.App,qabbtn);
            
            this.App.Visible = true;
        end
    end
    
    methods(Hidden)        
        function showApp(this)
            %Show an already esitsting instance of the app
            this.App.bringToFront();
        end
    end
    
    methods(Access = {?internal.EconModeler.ReportGenerator,?internal.EconModeler.FigureFactory})
        function items = getAllFigures(this)
            %Return all figures currently open in the app
            items = this.App.getDocuments();
            items = [items{:}];
            if isempty(items)
                items = internal.EconModeler.EconComponents.AbstractFigure.empty();
            end
        end
    end
    
    methods(Access = {?internal.EconModeler.Toolstrip.ToolStripDisplay,?internal.EconModeler.Tabs.AbstractContextualTab})
        function addTabGroup(this,tabGroup)
            %Add a TabGroup to the Toolstrip
            this.App.addTabGroup(tabGroup);
        end
    end
    
    methods(Access = {?internal.EconModeler.EconComponents.AbstractEconComponent,...
            ?internal.EconModeler.ModelDataBrowser,?internal.EconModeler.TimeSeriesDataBrowser})
        %Make sure that a given name does not already exist for current
        %time series, models, and figures, append number to name to ensure
        %uniqueness
        function uniqueName = makeUniqueWSName(this,name)
            if length(name) > namelengthmax
                name = name(1:namelengthmax);
            end
            inList = this.TimeSeriesList.isNameInList(name) || ...
                this.ModelList.isNameInList(name) || ...
                this.doFiguresHaveName(name);
            if ~inList
                uniqueName = name;
            else
                nextNum = 1;
                while inList
                    nextNum = nextNum + 1;
                    if length(name) > namelengthmax - length(num2str(nextNum))
                        nextName = [name(1:namelengthmax - length(num2str(nextNum))), num2str(nextNum)];
                    else
                        nextName = [name num2str(nextNum)];
                    end
                    inList = this.TimeSeriesList.isNameInList(nextName) || ...
                        this.ModelList.isNameInList(nextName) || ...
                        this.doFiguresHaveName(nextName);
                end
                uniqueName = nextName;
            end
        end
    end
    
    methods(Access = {?internal.EconModeler.FigureFactory,?internal.EconModeler.ModelFactory...
            ?internal.EconModeler.TimeSeriesFactory,?internal.EconModeler.Toolstrip.ToolStripDisplay})
        function selections = getSelections(this)
            %Concatenate selected time series and models
            selections = [this.SelectedTimeSeries, this.SelectedModels];
        end
    end
    
    methods(Access = {?internal.EconModeler.TimeSeriesDataBrowser,...
            ?internal.EconModeler.EconComponents.AbstractFigure,?internal.EconModeler.Dialogs.ReportDialog,...
            ?internal.EconModeler.Dialogs.UIARIMAXParameterDialog,?internal.EconModeler.Dialogs.UISARIMAXParameterDialog,...
            ?internal.EconModeler.Dialogs.UIMLRParameterDialog,?internal.EconModeler.Dialogs.UIRegARIMAParameterDialog,...
            ?internal.EconModeler.Dialogs.UIMLRParameterDialog,?internal.EconModeler.Dialogs.UIVARXParameterDialog,...
            ?internal.EconModeler.Dialogs.ExportDialog,?internal.EconModeler.Toolstrip.ToolStripDisplay})
        function items = getAllTimeSeries(this)
            %Return all time series in app
            items = getAllItems(this.TimeSeriesList);
        end
    end
    
    methods(Access = {?internal.EconModeler.ModelFactory,?internal.EconModeler.TimeSeriesDataBrowser,...
            ?internal.EconModeler.ReportGenerator,?internal.EconModeler.Dialogs.ExportDialog})
        function item = getTimeSeries(this,idx)
            %Return a time series given an identifier
            item = getItem(this.TimeSeriesList,idx);
        end
    end
    
    methods(Access = {?internal.EconModeler.ModelDataBrowser,?internal.EconModeler.ReportGenerator,...
            ?internal.EconModeler.Toolstrip.ToolStripDisplay,?internal.EconModeler.Dialogs.ExportDialog})
        function item = getModel(this,name)
            %Return a model given a identifier
            item = getItem(this.ModelList,name);
        end
    end
    
    methods(Access = {?internal.EconModeler.ModelDataBrowser,?internal.EconModeler.EconComponents.AbstractFigure,...
            ?internal.EconModeler.Dialogs.ReportDialog,?internal.EconModeler.Dialogs.ExportDialog,...
            ?internal.EconModeler.Toolstrip.ToolStripDisplay})
        function items = getAllModels(this)
            %Return all models in app
            items = getAllItems(this.ModelList);
        end
    end
    
        
    methods(Access = ?internal.EconModeler.FigureFactory)
        function addFigure(this,fig)
            %Add a figure to the app, no contextual tab is included
            fig.makeVisible();
            this.App.addDocument(fig);
        end
    end
   
    methods(Access = {?internal.EconModeler.Dialogs.UIModelParameterDialog,...
            ?internal.EconModeler.Dialogs.UIMLRParameterDialog,...
            ?internal.EconModeler.Dialogs.UIVARParameterDialog,...
            ?internal.EconModeler.Dialogs.UIVECComponentParameterDialog,...
            ?internal.EconModeler.Dialogs.UIVECImpactParameterDialog})
        function requestEstimate(this,e)
            this.ModelFactory.determineModelType([],e);
        end
    end
    
    methods(Access = private)
        
        function buildContexts(this)
            %Build the context for each contextual tab in the app
            
            %TS Plot
            tsPlotGroupOptions.Tag = 'TSPlot';
            tsPlotGroupOptions.Title = getString(message('econ:econModeler:TimeSeriesPlot'));
            tsPlotGroup = matlab.ui.internal.FigureDocumentGroup(tsPlotGroupOptions); 
            this.App.add(tsPlotGroup);
            
            %Model Fit Plot
            modelFitPlotGroupOptions.Tag = 'ModelFitPlot';
            modelFitPlotGroupOptions.Title = getString(message('econ:econModeler:ModelFitPlot'));
            modelFitPlotGroup = matlab.ui.internal.FigureDocumentGroup(modelFitPlotGroupOptions);
            this.App.add(modelFitPlotGroup);
            
            %ACF Tab
            acfGroupOptions.Tag = 'ACFPlot';
            acfGroupOptions.Title = getString(message('econ:econModeler:ACFTSTitle'));
            acfGroupOptions.Context = matlab.ui.container.internal.appcontainer.ContextDefinition();
            acfGroupOptions.Context.ToolstripTabGroupTags = 'acfTabGroup';
            acfPlotGroup = matlab.ui.internal.FigureDocumentGroup(acfGroupOptions);
            this.App.add(acfPlotGroup);
            
            %PACF Tab
            pacfGroupOptions.Tag = 'PACFPlot';
            pacfGroupOptions.Title = getString(message('econ:econModeler:PACFTitle'));
            pacfGroupOptions.Context = matlab.ui.container.internal.appcontainer.ContextDefinition();
            pacfGroupOptions.Context.ToolstripTabGroupTags = 'pacfTabGroup';
            pacfPlotGroup = matlab.ui.internal.FigureDocumentGroup(pacfGroupOptions);
            this.App.add(pacfPlotGroup);
            
            %YY Plot
            yyPlotGroupOptions.Tag = 'YYPlot';
            yyPlotGroupOptions.Title = getString(message('econ:econModeler:YYTitle'));
            yyPlotGroup = matlab.ui.internal.FigureDocumentGroup(yyPlotGroupOptions);
            this.App.add(yyPlotGroup);
            
            %Correlations Plot
            correlationsGroupOptions.Tag = 'CorrelationsPlot';
            correlationsGroupOptions.Title = getString(message('econ:econModeler:CORRSTitle'));
            correlationsGroup = matlab.ui.internal.FigureDocumentGroup(correlationsGroupOptions);
            this.App.add(correlationsGroup);
            
            %ADF Test
            adfTestGroupOptions.Tag = 'ADFFigure';
            adfTestGroupOptions.Title = getString(message('econ:econModeler:ADFTitle'));
            adfTestGroupOptions.Context = matlab.ui.container.internal.appcontainer.ContextDefinition();
            adfTestGroupOptions.Context.ToolstripTabGroupTags = 'adfTabGroup';
            adfTestGroup = matlab.ui.internal.FigureDocumentGroup(adfTestGroupOptions);
            this.App.add(adfTestGroup);
            
            %KPSS Test
            kpssTestGroupOptions.Tag = 'KPSSFigure';
            kpssTestGroupOptions.Title = getString(message('econ:econModeler:KPSSTitle'));
            kpssTestGroupOptions.Context = matlab.ui.container.internal.appcontainer.ContextDefinition();
            kpssTestGroupOptions.Context.ToolstripTabGroupTags = 'kpssTabGroup';
            kpssTestGroup = matlab.ui.internal.FigureDocumentGroup(kpssTestGroupOptions);
            this.App.add(kpssTestGroup);
            
            %LMC Test
            lmcTestGroupOptions.Tag = 'LMCFigure';
            lmcTestGroupOptions.Title = getString(message('econ:econModeler:LMCTitle'));
            lmcTestGroupOptions.Context = matlab.ui.container.internal.appcontainer.ContextDefinition();
            lmcTestGroupOptions.Context.ToolstripTabGroupTags = 'lmcTabGroup';
            lmcTestGroup = matlab.ui.internal.FigureDocumentGroup(lmcTestGroupOptions);
            this.App.add(lmcTestGroup);
            
            % PP Test
            ppTestGroupOptions.Tag = 'PPFigure';
            ppTestGroupOptions.Title = getString(message('econ:econModeler:PPTitle'));
            ppTestGroupOptions.Context = matlab.ui.container.internal.appcontainer.ContextDefinition();
            ppTestGroupOptions.Context.ToolstripTabGroupTags = 'ppTabGroup';
            ppTestGroup = matlab.ui.internal.FigureDocumentGroup(ppTestGroupOptions);
            this.App.add(ppTestGroup);
            
            % VRatio Test
            vratioTestGroupOptions.Tag = 'VRatioFigure';
            vratioTestGroupOptions.Title = getString(message('econ:econModeler:VRatioTitle'));
            vratioTestGroupOptions.Context = matlab.ui.container.internal.appcontainer.ContextDefinition();
            vratioTestGroupOptions.Context.ToolstripTabGroupTags = 'vratioTabGroup';
            vratioTestGroup = matlab.ui.internal.FigureDocumentGroup(vratioTestGroupOptions);
            this.App.add(vratioTestGroup);
            
            %Engle's ARCH Test
            archTestGroupOptions.Tag = 'ARCHFigure';
            archTestGroupOptions.Title = getString(message('econ:econModeler:ARCHTitle'));
            archTestGroupOptions.Context = matlab.ui.container.internal.appcontainer.ContextDefinition();
            archTestGroupOptions.Context.ToolstripTabGroupTags = 'archTabGroup';
            archTestGroup = matlab.ui.internal.FigureDocumentGroup(archTestGroupOptions);
            this.App.add(archTestGroup);
            
            %LBQ Test
            lbqTestGroupOptions.Tag = 'LBQFigure';
            lbqTestGroupOptions.Title = getString(message('econ:econModeler:LBQTitle'));
            lbqTestGroupOptions.Context = matlab.ui.container.internal.appcontainer.ContextDefinition();
            lbqTestGroupOptions.Context.ToolstripTabGroupTags = 'lbqTabGroup';
            lbqTestGroup = matlab.ui.internal.FigureDocumentGroup(lbqTestGroupOptions);
            this.App.add(lbqTestGroup);
            
            %Collinearity Test
            collinTestGroupOptions.Tag = 'CollinPlot';
            collinTestGroupOptions.Title = getString(message('econ:econModeler:CollinTitle'));
            collinTestGroupOptions.Context = matlab.ui.container.internal.appcontainer.ContextDefinition();
            collinTestGroupOptions.Context.ToolstripTabGroupTags = 'collinTabGroup';
            collinTestGroup = matlab.ui.internal.FigureDocumentGroup(collinTestGroupOptions);
            this.App.add(collinTestGroup);
            
            %EGCI Test
            egciTestGroupOptions.Tag = 'EGCIFigure';
            egciTestGroupOptions.Title = getString(message('econ:econModeler:EGCITitle'));
            egciTestGroupOptions.Context = matlab.ui.container.internal.appcontainer.ContextDefinition();
            egciTestGroupOptions.Context.ToolstripTabGroupTags = 'egciTabGroup';
            egciTestGroup = matlab.ui.internal.FigureDocumentGroup(egciTestGroupOptions);
            this.App.add(egciTestGroup);
            
            %JCI Test
            jciTestGroupOptions.Tag = 'JCIFigure';
            jciTestGroupOptions.Title = getString(message('econ:econModeler:JCITitle'));
            jciTestGroupOptions.Context = matlab.ui.container.internal.appcontainer.ContextDefinition();
            jciTestGroupOptions.Context.ToolstripTabGroupTags = 'jciTabGroup';
            jciTestGroup = matlab.ui.internal.FigureDocumentGroup(jciTestGroupOptions);
            this.App.add(jciTestGroup);
            
            %Histogram Plot
            histogramPlotGroupOptions.Tag = 'HistogramPlot';
            histogramPlotGroupOptions.Title = getString(message('econ:econModeler:HistTitle'));
            histogramGroupOptions = matlab.ui.internal.FigureDocumentGroup(histogramPlotGroupOptions);
            this.App.add(histogramGroupOptions);
            
            %QQ Plot
            qqPlotGroupOptions.Tag = 'QQPlot';
            qqPlotGroupOptions.Title = getString(message('econ:econModeler:QQTitle'));
            qqGroupOptions = matlab.ui.internal.FigureDocumentGroup(qqPlotGroupOptions);
            this.App.add(qqGroupOptions);
        end
        
        function setWaiting(this,val)
            %Toggle the app's "waiting"
            this.App.Busy = val;
        end
        
        function check = doFiguresHaveName(this,name)
            allFigures = this.App.getDocuments();
            if isempty(allFigures)
                check = false;
                return;
            end
            allFigures = [allFigures{:}];
            allNames = {allFigures.Name};
            check = any(strcmp(name,allNames));
        end
        
        function checkBeforeImport(this,~,e)
            import internal.EconModeler.EventData.NewTimeSeriesEventData
            %Check to see if any objects (time series, models,figures) are
            %in the app before importing. Ask user if they want to clear
            %previous work before proceeding
            allItems = [this.TimeSeriesList.getAllItems();...
                this.ModelList.getAllItems();...
                this.getAllFigures()'];
            if ~isempty(allItems)
                title = getString(message('econ:econModeler:AppTitle'));
                question = getString(message('econ:econModeler:ImportQuestion'));
                confirm = getString(message('econ:econModeler:OK'));
                cancel =  getString(message('econ:econModeler:Cancel'));
                response = questdlg(question,title,confirm,cancel,cancel);
                
                if ~strcmp(response,confirm)
                    return;
                end
            end
            
            notify(this,'NewTimeSeriesRequest',e);
        end
               
        function approved = closeConfirm(this)
            %Check if user really want to close 
            selection = questdlg(getString(message('econ:econModeler:ConfirmClose')),...
                    getString(message('econ:econModeler:AppTitle')),...
                    getString(message('econ:econModeler:Yes')),...
                    getString(message('econ:econModeler:No')),...
                    getString(message('econ:econModeler:No')));
                switch selection
                    case getString(message('econ:econModeler:Yes'))
                        approved = true;
                        notify(this,'AppClosed');
                    otherwise
                        approved = false;
                end 
        end
        
        function generateFunction(this,type)
            
            type = validatestring(type,["plain","live"]);
            
            %Set bold and italic markup based on whether or not this is a
            %live function
            if type == "live"
                boldSymbol = '*';
                italicSymbol = '_';
            else
                boldSymbol = '';
                italicSymbol = '';
            end
            
            %Generate the code to produce the selected model
            modelToCreate = this.SelectedModels;
            if length(modelToCreate) ~= 1
                uialert(this.App,getString(message('econ:econModeler:SingleModelCodeGen')),...
                    getString(message('econ:econModeler:AppTitle')),...
                    'Icon','error','Modal',true);
                return;
            end
            
            %Create the function header
            funcString = ['function ',modelToCreate.Name,' = modelTimeSeries(',this.OriginalVariable,')',newline];
            
            funcString = [funcString, '%%',getString(message('econ:econModeler:MLXTitle')), newline];
            
            
            %funcString = [funcString, '% ', modelToCreate.Name,' = modelTimeSeries(',this.OriginalVariable,')',newline];
            desc = getString(message('econ:econModeler:CodeDescription'));
            desc = strrep(desc,newline,[newline, '%']);
            funcString = [funcString,'% ',desc,newline,'%',newline];
            funcString = [funcString,'%',boldSymbol,getString(message('econ:econModeler:Input')),boldSymbol,' '];
            switch this.OriginalClass
                case 'double'
                    inputString = getString(message('econ:econModeler:DoubleInput'));
                case 'table'
                    inputString = getString(message('econ:econModeler:TableInput'));
                otherwise
                    inputString = getString(message('econ:econModeler:TimeTableInput'));
            end
            funcString = [funcString,inputString];
            funcString = [funcString,' ',italicSymbol,'(',this.OriginalVariable,')',italicSymbol,newline,'%',newline];
            funcString = [funcString,'%',boldSymbol,getString(message('econ:econModeler:Output')),boldSymbol,' '];
            funcString = [funcString,getString(message('econ:econModeler:OutputDescription')),' ',italicSymbol,'(',modelToCreate.Name,')',italicSymbol];
            funcString = [funcString,newline,'%',newline];
            
            econInfo = ver('econ');
            currentTime = datestr(now);
            funcString = [funcString,'%',italicSymbol,getString(message('econ:econModeler:VersionInfo',econInfo.Release,...
                econInfo.Name,econInfo.Version,currentTime)),italicSymbol,...
                newline];
            
            funcString = modelToCreate.writeCode(funcString,type);
            funcString = [funcString, 'end'];
            
            if type == "live"
                matlab.internal.liveeditor.openAsLiveCode(funcString);
            else
                document = matlab.desktop.editor.newDocument(funcString);
                document.smartIndentContents();
            end
            
            allItems = [this.getAllTimeSeries;this.getAllModels];
            for n = 1:length(allItems)
                allItems(n).Written = false;
            end
            
        end
        
        function setupTab(this,~,e)
           
            if ~isempty(this.App.getDocuments)
                 %Update contextual tab to act on the newly focused figure
                 if e.PropertyName == "LastSelectedDocument" 
                    figStruct = this.App.LastSelectedDocument;
                    fig = this.App.getDocument(figStruct.documentGroupTag,figStruct.tag);

                    if isa(fig,'internal.EconModeler.EconComponents.Figures.ACFPlot')
                        this.ContextualTabList.getACFTab.setFig(fig);
                    elseif isa(fig,'internal.EconModeler.EconComponents.Figures.PACFPlot')
                        this.ContextualTabList.getPACFTab.setFig(fig);
                    elseif isa(fig,'internal.EconModeler.EconComponents.Figures.CrossCorrPlot')
                        this.ContextualTabList.getCrossCorrTab.setFig(fig);
                    elseif isa(fig,'internal.EconModeler.EconComponents.Figures.CollinPlot')
                        this.ContextualTabList.getCollinTab.setFig(fig);
                    elseif isa(fig,'internal.EconModeler.EconComponents.Figures.ADFFigure')
                        this.ContextualTabList.getADFTab.setFig(fig);
                    elseif isa(fig,'internal.EconModeler.EconComponents.Figures.KPSSFigure')
                        this.ContextualTabList.getKPSSTab.setFig(fig);
                    elseif isa(fig,'internal.EconModeler.EconComponents.Figures.LMCFigure')
                        this.ContextualTabList.getLMCTab.setFig(fig);
                    elseif isa(fig,'internal.EconModeler.EconComponents.Figures.PPFigure')
                        this.ContextualTabList.getPPTab.setFig(fig);
                    elseif isa(fig,'internal.EconModeler.EconComponents.Figures.VRatioFigure')
                        this.ContextualTabList.getVRatioTab.setFig(fig);
                    elseif isa(fig,'internal.EconModeler.EconComponents.Figures.ARCHFigure')
                        this.ContextualTabList.getARCHTab.setFig(fig);
                    elseif isa(fig,'internal.EconModeler.EconComponents.Figures.LBQFigure')
                        this.ContextualTabList.getLBQTab.setFig(fig);
                    elseif isa(fig,'internal.EconModeler.EconComponents.Figures.EGCIFigure')
                        this.ContextualTabList.getEGCITab.setFig(fig);
                    elseif isa(fig,'internal.EconModeler.EconComponents.Figures.JCIFigure')
                        this.ContextualTabList.getJCITab.setFig(fig);
                    else
                        return;
                    end
                 end
            end
        end
            
        function updateTimeseriesSelections(this,~,e)
            %Update tiem series selections
            if isempty(e.TimeSeries)
                this.SelectedTimeSeries = [];
            else
                this.SelectedTimeSeries = [e.TimeSeries];
            end
            
            %Deselect models if any time series are selected
            if length(this.SelectedTimeSeries) >= 1
                this.SelectedModels = [];
                clearSelections(this.ModelDataBrowser);
            end
            notify(this,'SelectionsUpdated');
        end
        
        function updateModelSelections(this,~,e)
            %Update model selections
            if isempty(e.Model)
                this.SelectedModels = [];
            else
                this.SelectedModels = [e.Model];
            end
            
            %Deselct Time Series if any models are selected
            if length(this.SelectedModels) >= 1
                this.SelectedTimeSeries = [];
                clearSelections(this.TSDataBrowser);
            end
            
            notify(this,'SelectionsUpdated');  
        end
        
        function cleanupTimeSeriesSelections(this,~,~)
            %Remove cleared time series from selections
            idx = false(length(this.SelectedTimeSeries),1);
            for n = 1:length(this.SelectedTimeSeries)
                idx(n) = this.TimeSeriesList.isNameInList(this.SelectedTimeSeries(n).Name);
            end
            this.SelectedTimeSeries(~idx)=[];
            notify(this,'SelectionsUpdated');
        end
        
        function cleanupModelSelections(this,~,~)
            %Remove cleared models from selection
            idx = false(length(this.SelectedModels),1);
            for n = 1:length(this.SelectedModels)
                idx(n) = this.ModelList.isNameInList(this.SelectedModels(n).Name);
            end
            this.SelectedModels(~idx)=[];
            notify(this,'SelectionsUpdated');
        end
        
        function clearAllItems(this)
            %Clear all items from the app
            %this.FigureList.clearAll();
            this.ModelList.clearAll();
            this.TimeSeriesList.clearAll();
            allDocuments = this.App.getDocuments();
            for n = 1:length(allDocuments)
                close(allDocuments{n});
            end
            %this.App.Layout.documentLayout.gridDimensions = [1 1];
            drawnow;
        end
        
        function cleanup(this,~,~)
            if this.App.State == matlab.ui.container.internal.appcontainer.AppState.TERMINATED
                delete(this)
            end
        end
    end
    
    methods(Access = private,Static)
        function launchEconModelerHelp(~,~)
            helpview('econ','econmodeler_refpg');
        end
    end
end

