classdef ExportOptimizationHandler
    % Class to handle the export optimization workflow to script.
    
    % Copyright 2020 The MathWorks, Inc.
    
    methods
        function response = handle(this, clientData)  
            response.isSuccess = false;
            
            %% generate the optimization workflow script
            try
                exportScript = this.generateScript(clientData.FileName);
            catch e                 
                response.message = e.message;
                return;
            end
            
            %% write the generated script to user specified file
            try
                fileName = clientData.FileName + ".m";
                this.printScript(exportScript, fileName);
                
            catch
                response.message = fxptui.message('textExportError');
                return;
            end
            
            response.isSuccess = true;
            response.message = fxptui.message('textExportSuccess', fileName);
        end
    end
    
    methods(Hidden)
        function currentWorkflow = getCurrentWorkflow(~)
            % extract current workflow from the depot
            fptInstance = fxptui.FixedPointTool.getExistingInstance();
            model = fptInstance.getModel();
            dataLayer = fxptds.DataLayerInterface.getInstance();
            currentWorkflow = dataLayer.getCurrentWorkflow(model);
        end
        
        function [designSettings, optimizationSetting] = getExportSettings(this)
            % extract workflow settings to generate script        
            currentWorkflow = this.getCurrentWorkflow();
            workflowSetting = currentWorkflow.WorkflowSetting;                
            designSettings = workflowSetting.getSettingValue('DesignSetting');
            optimizationSetting = workflowSetting.getSettingValue('OptimizationSetting');
        end
        
        function script = generateScript(this, fileName)
            % extract settings to generate the script
            [designSettings, optimizationSetting] = this.getExportSettings();           
                
            % generate script for the optimization workflow
            script = [];
            script = this.addModelInfo(designSettings, script);
            script = this.addSUDInfo(designSettings, script);  
            script = this.addOptionsInfo(optimizationSetting, script, fileName);
            script = this.addRunInfo(script);
            script = this.addExploreInfo(script);
        end
        
        function printScript(~, script, fileName)
            % export the generated script to specified file                
            fid = fopen(fileName, "w+");
            for fIndex = 1:numel(script)
                fprintf(fid, "%s\n\n", script(fIndex));
            end
            fclose(fid);
        end
        
        function script = addModelInfo(~, settings, script)
            % extract and add model info to the script
            info = "model = " + mat2str(settings.TopModel) + ";";
            script = [script; info];
        end
        
        function script = addSUDInfo(~, settings, script)
            % extract and add SUD info to the script
            info = "sud = " + mat2str(settings.SelectedSystemToScale) + ";";
            script = [script; info];
        end
        
        function script = addOptionsInfo(~, settings, script, fileName)           
            % extract and add optimization options info to the script   
            optionsScribe = DataTypeOptimization.FxpOptimizationOptionsScribe(settings, fileName);
            info = optionsScribe.finalStr;
            script = [script; info];
        end
        
        function script = addRunInfo(~, script)
            % add optimize command to the script
            info = "result = fxpopt(model, sud, options);";
            script = [script; info];
        end
        
        function script = addExploreInfo(~, script)
            % add explore command to the script
            info = "explore(result);";
            script = [script; info];
        end
    end
end