classdef ExportDialog < handle
    %EXPORTDIALOG Dialog for exporting variables in the econModeler app
    
    %Copyright 2017 The MathWorks Inc.
    
    properties(Access = private)
        Session
        Figure                          matlab.ui.Figure
        TimeSeriesTable                 matlab.ui.control.Table
        ModelTable                      matlab.ui.control.Table
        ExportButton                    matlab.ui.control.Button
        CancelButton                    matlab.ui.control.Button
        Listeners                       cell
    end
    
    methods(Access = ?internal.EconModeler.DialogFactory)
        function this = ExportDialog(session)
            
            this.Session = session;
            
            %Create UI Components
            this.Figure = uifigure('Name', getString(message('econ:econModeler:ExportFigName')),...
                'Position',[100 100 641 243],...
                'CloseRequestFcn',@this.closeCallback,...
                'Tag','exportFigure',...
                'UserData',@(x,y)this.qeCheckVariables(x,y),...
                'WindowStyle','modal',...
                'Visible','off');

            matlab.graphics.internal.themes.figureUseDesktopTheme(this.Figure);
            
            grid = uigridlayout(this.Figure,[2 1],'RowHeight',{'1x','fit'});
            topRow = uigridlayout(grid,[1 2],'ColumnWidth',{'1x','1x'});
            topRow.Layout.Row = 1;
            bottomRow = uigridlayout(grid,[1 3],'ColumnWidth',{'1x','fit','fit'});
            bottomRow.Layout.Row = 2;
            
            %Create Time Series Table
            ts = this.Session.getAllTimeSeries();
            tsNames = {ts.Name}';
            selectedTS = get(this.Session.SelectedTimeSeries,'Name');
            [~,idxToCheck] =  intersect(tsNames,selectedTS);
            selections = false(length(ts),1);
            selections(idxToCheck) = true;
            tsTableData = [num2cell(selections),tsNames];
            this.TimeSeriesTable = uitable(topRow,...
                'Data',tsTableData,...
                'ColumnName',{getString(message('econ:econModeler:Select')),getString(message('econ:econModeler:TSColumnName'))},...
                'ColumnEditable',[true,false],...
                'CellEditCallback',@this.checkSelections,...
                'Tag','timeseriesTable');
            this.TimeSeriesTable.Layout.Column = 1;
            
            %Create model Table
            mdls = this.Session.getAllModels();
            mdlNames = {mdls.Name}';
            selectedModels = get(this.Session.SelectedModels,'Name');
            [~,idxToCheck] =  intersect(mdlNames,selectedModels);
            selections = false(length(mdls),1);
            selections(idxToCheck) = true;
            mdlTableData = [num2cell(selections),mdlNames];
            this.ModelTable = uitable(topRow,...
                'Data',mdlTableData,...
                'ColumnName',{getString(message('econ:econModeler:Select')),getString(message('econ:econModeler:ModelColumnName'))},...
                'ColumnEditable',[true,false],...
                'CellEditCallback',@this.checkSelections,...
                'Tag','modelTable');
            this.ModelTable.Layout.Column = 2;
            
            this.ExportButton = uibutton(bottomRow,'push',...
                'Position',[401 21 100 22],...
                'Text',getString(message('econ:econModeler:Export')),...
                'Tag','exportButton',...
                'ButtonPushedFcn',@this.exportVariables,...
                'Enable','off');
            this.ExportButton.Layout.Column = 2;
            
            this.CancelButton = uibutton(bottomRow,'push',...
                'Position',[520 21 100 22],...
                'Text',getString(message('econ:econModeler:Cancel')),...
                'Tag','cancelButton',...
                'ButtonPushedFcn',@this.closeFigure);
            this.CancelButton.Layout.Column = 3;
               
            %Enable Export if there are any selections
            if (~isempty(this.TimeSeriesTable.Data) && any([this.TimeSeriesTable.Data{:,1}])) || ...
                    (~isempty(this.ModelTable.Data) && any([this.ModelTable.Data{:,1}]))
                this.ExportButton.Enable = 'on';
            end
            
            movegui(this.Figure,'center');
            this.Figure.Visible = 'on';    
            
            this.Listeners{end+1} = event.listener(this.Session,'AppClosed',@(s,e)closeCallback(this));
        end
    end
    
    methods(Access = private)
        function closeCallback(this,~,~)
            %Delete object as figure closes
            this.Session.notify('DialogClosed');
            delete(this.Figure)
            delete(this);
        end
        
        function closeFigure(this,~,~)
            close(this.Figure);
        end
        
        function checkSelections(this,~,~)
            if any([[this.TimeSeriesTable.Data{:,1}]';[this.ModelTable.Data{:,1}]'])
                this.ExportButton.Enable = 'on';
            else
                this.ExportButton.Enable = 'off';
            end
        end
        
        function exportVariables(this,~,~)
            %Export selected Variables to MATLAB workspace
            
            if ~isempty(this.TimeSeriesTable.Data)
                tsSelections = [this.TimeSeriesTable.Data{:,1}];
                selectedTimeSeries = cellstr(this.TimeSeriesTable.Data(tsSelections,2));
            else
                selectedTimeSeries = cell(0);
            end
            
            if ~isempty(this.ModelTable.Data)
                modelSelections = [this.ModelTable.Data{:,1}];
                selectedModels = cellstr(this.ModelTable.Data(modelSelections,2));
            else
                selectedModels = cell(0);
            end
            
            allVariables = [selectedTimeSeries;selectedModels];
            existingIdx = logical((cellfun(@(x)evalin('base',['exist(''',x,''',''var'')']),allVariables)));
            if any(existingIdx)
                existingNames = ['(',char(join(allVariables(existingIdx),',')),')'];
                button = questdlg(getString(message('econ:econModeler:RepeatVariable',existingNames)),...
                    getString(message('econ:econModeler:AppTitle')),...
                    getString(message('econ:econModeler:Yes')),...
                    getString(message('econ:econModeler:No')),...
                    getString(message('econ:econModeler:Yes')));
                switch button
                    %Cancel import if user selects No or Cancel, or closes
                    %dialog
                    case {getString(message('econ:econModeler:No')),''}
                        return;
                end
            end
            
            for n = 1:length(selectedTimeSeries)
                tsToExport = this.Session.getTimeSeries(selectedTimeSeries{n});
                export(tsToExport);
            end
            
            for n = 1:length(selectedModels)
                modelToExport = this.Session.getModel(selectedModels{n});
                export(modelToExport);
            end
            
            %Close figure when operation is complete
            close(this.Figure);
        end 
    end 
    
    methods(Hidden,Access = public)
        function qeCheckVariables(this,t,selection)
            if strcmpi(t,'Time Series')
                this.TimeSeriesTable.Data{selection,1} = ~this.TimeSeriesTable.Data{selection,1};
            elseif strcmpi(t,'Model')
                this.ModelTable.Data{selection,1} = ~this.ModelTable.Data{selection,1};
            end
            this.checkSelections();
        end
    end
                
end

