classdef DataLayerInterface < handle
    %% DATALAYERINTERFACE class implements a singleton instance which acts as a unified gateway for accessing fxptds.* APIs
    
    %   Copyright 2016-2020 The MathWorks, Inc.
    
    methods (Static)
        function obj = getInstance
            % Returns the stored instance of the repository.
            persistent localObj
            if isempty(localObj) || ~isvalid(localObj)
                localObj = fxptds.DataLayerInterface;
            end
            obj = localObj;
        end
    end
    
    methods (Access=private)
        function this = DataLayerInterface
            
        end
    end
    methods
        runNames = getAllRunNamesWithResults(this, dataset);
        runNames = getAllRunNamesForProposal(this, dataset);
        runNames = getAllRunNamesUsingApplicationData(this, applicationData);
        runNames = getAllRunNamesUsingModelSource(this, modelName);
        runNames = getAllRunNamesWithSignalLoggingResults(this,  dataset);
        runNames = getAllRunNamesUnderModel(this, modelName);
        results = getAllResultsFromRunUsingModelSource(this, modelName, runName);
        
        [resultIds, resultInfo] = queryResults(this,  modelName, blockObject, pathItem, runName);
        
        hasAction = hasExecutedAction(this, modelName, runName, action);
        % embedded run name management
        % NOTE: this functionality will be moved to an external layer, see
        % g1450668
        addEmbeddedRunName(this, modelName, embeddedRunName);
        removeEmbeddedRunName(this, modelName, embeddedRunName);
        clearEmbeddedRunName(this, modelName, embeddedRunName);
        
        function facade = getWorkflowTopologyFacade(~, modelName)
            % Creates a Facade object with a pointer to the FPTRepository
            % DesignStore
            fptRepository = fxptds.FPTRepository.getInstance;
            dataset = fptRepository.getDatasetForSource(modelName);
            facade = dataset.WorkflowTopologyFacade;
        end
        
        function addWorkflow(~, modelName, intent)
            fptRepository = fxptds.FPTRepository.getInstance();
            dataset = fptRepository.getDatasetForSource(modelName);
            
            id = numel(dataset.WorkflowStore) + 1;
            workflow = fxptui.internal.workflow.Workflow(id, intent);
            dataset.addWorkflow(workflow);
            
        end
        
        function workflow = getCurrentWorkflow(~, modelName)
            fptRepository = fxptds.FPTRepository.getInstance();
            dataset = fptRepository.getDatasetForSource(modelName);
            id = dataset.CurrentWorkflowID;
            workflow = dataset.getWorkflowByID(id);
        end
        
        function addDepotUnit(~, modelName, depotUnit)
            fptRepository = fxptds.FPTRepository.getInstance();
            dataset = fptRepository.getDatasetForSource(modelName);
            dataset.WorkflowDepot.addUnit(depotUnit);
        end
        
        function depotUnits = getWorkflowUnitsByWorkflowID(~, modelName, workflowID)
            fptRepository = fxptds.FPTRepository.getInstance();
            dataset = fptRepository.getDatasetForSource(modelName);
            depotUnits = dataset.WorkflowDepot.getUnitsByWorkflowID(workflowID);
        end
        
        function results = getResultsByWorkflowID(this, modelName, workflowID, type)
            if nargin == 3
                type = '';
            end
            
            % get all the depot units for the given model and workflow
            depotUnits = this.getWorkflowUnitsByWorkflowID(modelName, workflowID);
            
            % create a cell array of results and return all matching units
            results = cell(size(depotUnits));
            for idx = 1:numel(depotUnits)
                unit = depotUnits(idx);
                results{idx} = unit.Result;
            end
            
            if ~isempty(type)
                matchingResults = cellfun(@(x) isa(x, type), results);
                results = results(matchingResults);
            end
        end
        
        function depotLength = getWorkflowDepotCount(~, modelName)
            fptRepository = fxptds.FPTRepository.getInstance();
            dataset = fptRepository.getDatasetForSource(modelName);
            depotLength = dataset.WorkflowDepot.Count;
        end
        
        function b = isRunVerificationRun(~, modelName, runName)
            % Returns a boolean to whether a given run name for a model is
            % from an Embedded run
            fptRepository = fxptds.FPTRepository.getInstance;
            dataset = fptRepository.getDatasetForSource(modelName);
            b = contains(runName, dataset.EmbeddedRunNames);
            
        end
        
        function [sdiRunID, fptRunID] = getIdFromRunName(~, modelName, runName)
            % Parses the run object given a RunName for the SDI run ID and
            % the FPT run ID
            
            fptRepository = fxptds.FPTRepository.getInstance;
            dataset = fptRepository.getDatasetForSource(modelName);
            if dataset.containsRunWithName(runName)
                runObj = dataset.getRun(runName);
                sdiRunID = runObj.getTimeSeriesRunID;
                fptRunID = runObj.RunID;
            else
                sdiRunID = [];
                fptRunID = [];
            end
        end
        
        function targetRunName = getRunNameFromID(~, modelName, fptRunIDs)
            % Given a FPTRun.RunID return the char RunName
            
            % initialize a cell array of length equal to that of the number
            % of ID's given
            numIDs = numel(fptRunIDs);
            targetRunName = repmat({''},1,numIDs);
            
            fptRepository = fxptds.FPTRepository.getInstance;
            dataset = fptRepository.getDatasetForSource(modelName);
            
            
            for idx = 1:numIDs
                fptRunID = fptRunIDs(idx);
                
                % valid FPT RunID are keys in the map RunIDNameMap that
                % maps ID to runName
                %  the given fptRunID may be NaN if the ID was originally
                %  empty and then converted to a double
                if ~isnan(fptRunID) && dataset.RunIDNameMap.isKey(fptRunID)
                    % if the given fptID meets those requirements, then get
                    % the corresponding run object and run name
                    targetRunName{idx} = dataset.RunIDNameMap.getDataByKey(fptRunID);
                end
            end
            
            % return just the character vector rather than the cell array
            % if there is only 1 ID provided
            if numIDs == 1
                targetRunName = targetRunName{1};
            end
            
        end
        
        function sdiRunId = getSDIRunIDForLastCollection(this, modelName)
            % getSDIRunIDForLastCollection returns the sdi run id of the
            % last valid simulation
            facade = this.getWorkflowTopologyFacade(modelName);
            data = facade.query(modelName, 'type', 'Collection', 'property', 'SDIRunID', 'limit', 1);
            sdiRunId = data{:};
        end
        
        function setSignalTolerancesStore(~, topModel, models, sdiRunId)
            % UpdateSignalTolerancesStore updates the store in modelName's
            % dataset with the signal id and tolerance information
            fptRepository = fxptds.FPTRepository.getInstance;
            dataset = fptRepository.getDatasetForSource(topModel);
            dataset.SignalTolerancesStore.create(models, sdiRunId);
        end
        
        function updateSignalTolerancesStore(~, modelName, dataStore)
            % UpdateSignalTolerancesStoreData updates store information
            
            fptRepository = fxptds.FPTRepository.getInstance;
            dataset = fptRepository.getDatasetForSource(modelName);
            dataset.SignalTolerancesStore.update(dataStore);
        end
        
        function signalTolerancesStore = getSignalTolerancesStore(~, modelName)
            % GetSignalTolerancesStore gets the store data from dataset
            
            fptRepository = fxptds.FPTRepository.getInstance;
            dataset = fptRepository.getDatasetForSource(modelName);
            signalTolerancesStore = dataset.SignalTolerancesStore.DataStore;
        end
        
        function updateTolerances(~, modelName, toleranceVal)
            fptRepository = fxptds.FPTRepository.getInstance;
            dataset = fptRepository.getDatasetForSource(modelName);
            dataset.SignalTolerancesStore.updateTolerances(toleranceVal);
        end
        
        function clearSignalToleranceStore(~, modelName)
            fptRepository = fxptds.FPTRepository.getInstance;
            dataset = fptRepository.getDatasetForSource(modelName);
            dataset.SignalTolerancesStore.clear();
        end
        
    end
end

% LocalWords:  isclass
