classdef (Hidden = true) AnnotateManager < handle
% Singleton class to manage all open execution profiling informers.

%   Copyright 2010-2015 The MathWorks, Inc.
    
    properties(Access=private)
        Map_SimulationComponentToInformer;
    end

    methods(Access = private)
        
        
        function this = AnnotateManager()
            
            % Mapping from Simulation Component (g753348 > rfA) to corresponding 
            % informer object
            this.Map_SimulationComponentToInformer = ...
                containers.Map('KeyType', 'char', 'ValueType', 'any');
            
        end
    end
    
    methods(Access = public)

        function lSimulationComponents = ...
                getSimulationComponentsWithInformer(this)

            lSimulationComponents = ...
                this.Map_SimulationComponentToInformer.keys;
        
        end

        function informer = getInformerForSimulationComponent...
                (this, lSimulationComponent)
            informer = this.Map_SimulationComponentToInformer...
                (lSimulationComponent);
        end
        
        function createInformer(this, executionProfile, varargin)
            % When the execution time object becomes available, call this method to
            % create a new informer and highlight the associated models
        
            % Get the Simulation Component that the new informer must be
            % associated with
            lSimulationComponent = executionProfile.SimulationComponent;
            
            % Check if the informer for the current model is already open (occurs if
            % annotation is invoked from the command line)
            if this.Map_SimulationComponentToInformer.isKey(lSimulationComponent)
                coder.profile.AnnotateManager.tearDownInformer(lSimulationComponent);
            end

            % Create the new informer
            informer = coder.profile.Informer(executionProfile, varargin{:});
            if hasInformerWindow(informer)
                this.Map_SimulationComponentToInformer(lSimulationComponent) = informer;
                
                % Enable callbacks for model load etc
                exectime_profiling_callback('activate');
            end
            
        end 
        
        function processCallback(this, modelH, method)
            
            modelName = get_param(modelH, 'Name');
            
            %  Check if starting a new simulation
            if any(strcmp(method, {'init', 'close', 'forceClose'}))
                % Identify simulation components within this model, which have an open informer
                lSimulationComponentsAll = getSimulationComponentsWithInformer(this);
                
                % Extract model names from block specifications
                modelsForSimulationComponents = ...
                    coder.profile.private.getTopModelFromBlock(lSimulationComponentsAll);
                
                matchIdx = strcmp(modelsForSimulationComponents, modelName);
                lSimulationComponents = lSimulationComponentsAll(matchIdx);
                for i=1:length(lSimulationComponents)
                    coder.profile.AnnotateManager.tearDownInformer(lSimulationComponents(i));
                end
            end
            
            if strcmp(method, 'postLoad')
                % Notify informers in case they need to apply highlighting
                % for this model
                informers = this.Map_SimulationComponentToInformer.values;
                for i=1:length(informers)
                    loadModelCallback(informers{i}, modelName);
                end
            end
            
        end
    end
    
    methods(Static=true, Access=public)
        
        function obj = getAnnotateManagerInstance

            % Return the singleton object
            persistent singletonObj
            
            if ~isa(singletonObj, 'coder.profile.AnnotateManager')
                singletonObj = coder.profile.AnnotateManager();
            end
            obj = singletonObj;
            
        end     
         
        function tearDownInformer(lSimulationComponent)
            
            % Tear down informer associated with this top model simulation 
            inst = coder.profile.AnnotateManager.getAnnotateManagerInstance;
            if isKey(inst.Map_SimulationComponentToInformer, lSimulationComponent)
                % Deleting the reference to an informer invokes its delete method
                % (and this closes the informer window)
                inst.Map_SimulationComponentToInformer.remove(lSimulationComponent);
            end 
            
            if isempty(inst.Map_SimulationComponentToInformer.keys)
                % Switch off model callbacks
                exectime_profiling_callback('deActivate');
            end
            
        end
    end    
end

