classdef (Sealed) CaptureProbeComponentRegistry < coder.profile.ProbeComponentRegistry
% CaptureProbeComponentRegistry is the probe registry for ontarget data
% collection

% Copyright 2019 The MathWorks, Inc.

properties (Constant)
MaximumIdLength = 31;
MaxCaptureProbeType = 'max';
AvgCaptureProbeType = 'avg';
NumCallsCaptureProbeType = 'numcalls';
end

methods
function this = CaptureProbeComponentRegistry(componentName,...
componentRef,...
targetWordSize,...
buildDir,...
codeFolderRelative)
if nargin < 5
codeFolderRelative = '';
end
this = this@coder.profile.ProbeComponentRegistry(componentName,...
componentRef,...
targetWordSize,...
buildDir,...
coder.profile.CaptureProbeComponentRegistry.MaximumIdLength,...
codeFolderRelative);
this.registerProbeType(coder_profile_ProbeType.CAPTURE_PROBE);
end

function requestCaptureProbes(this, numElements)
this.requestMaxCaptureProbe(numElements);
this.requestAvgCaptureProbe(numElements);
this.requestCallCaptureProbe(numElements);
end

function probeFncCall = instrumentationFnc(this, lProbeType, lSectionId)
lProbeTypeName = coder_profile_ProbeType.toString(uint32(lProbeType));
probeRealInstrFncs =...
this.getProbeInstrumentationFcn(...
lProbeType,...
lSectionId);

probeInstrFncs =...
arrayfun(@(x) strcat(x, '_', this.ComponentName),...
probeRealInstrFncs);
probeFncCall = ...
arrayfun(@(x) coder.profile.private.createProbeIdentifier...
(x.name, this.MaxIdLength),...
cell2struct(probeInstrFncs, {'name'}, 1),...
'UniformOutput', false);

% check to see if we already have this name for the probe type
if this.ProbeCalls.isKey(lProbeTypeName)
% safety check
vals = this.ProbeCalls(lProbeTypeName);
assert(isequal(vals{1}, probeFncCall),...
'The wrapper probe calls should be same across the same probe type');
assert(isequal(vals{2}, probeRealInstrFncs),...
'The real instrumentation probe calls should be same across the same probe type');
else
vals = cell(1,2);
vals{1} = probeFncCall;
vals{2} = probeRealInstrFncs;
this.ProbeCalls(lProbeTypeName) = vals;
end
end

% Public Method: areEventCallbacksRequired -----------------------
% Abstract: this method states that the event callbacks are
% required (PauseEvent, StepCompletedEvent and TerminateEvent)
%
function eventCallbacksRequired = areEventCallbacksRequired(~)
eventCallbacksRequired = true;
end
end

methods (Access=private)
function id = requestCaptureProbe(this, type, numElements)
id = this.requestSectionId(...
coder_profile_ProbeType.CAPTURE_PROBE, type, numElements);

% fill in local SectionIds
probeTypeName = coder_profile_ProbeType.toString(coder_profile_ProbeType.CAPTURE_PROBE);
this.addInternalSectionId(probeTypeName, id);

this.checkMaxIdLimit(probeTypeName);

% add probe to ProbeCalls
this.instrumentationFnc(coder_profile_ProbeType.CAPTURE_PROBE, id);
end

function id = requestMaxCaptureProbe(this, numElements)
id = this.requestCaptureProbe(...
coder.profile.CaptureProbeComponentRegistry.MaxCaptureProbeType, ...
numElements);
end

function id = requestAvgCaptureProbe(this, numElements)
id = this.requestCaptureProbe(...
coder.profile.CaptureProbeComponentRegistry.AvgCaptureProbeType, ...
numElements);
end

function id = requestCallCaptureProbe(this, numElements)
id = this.requestCaptureProbe(...
coder.profile.CaptureProbeComponentRegistry.NumCallsCaptureProbeType, ...
numElements);
end
end
end