function DriftDetector = incrementalConceptDriftDetector(DetectionMethod,varargin)
%INCREMENTALCONCEPTDRIFTDETECTOR Incremental concept drift detector.
%
%   DETECTOR=INCREMENTALCONCEPTDRIFTDETECTOR(DETECTIONMETHOD) returns an incremental
%   concept drift detector that utilizes the method DETECTIONMETHOD. DETECTIONMETHOD can
%   be one of 'ddm' ([1]), 'hddma', or 'hddmw' ([2]).
%
%   DETECTOR=INCREMENTALCONCEPTDRIFTDETECTOR(DETECTIONMETHOD,'PARAM1',val1,'PARAM2',val2,...) specifies optional
%   parameter name-value arguments corresponding to provided DETECTIONMETHOD.
%
%   For DETECTIONMETHOD = 'ddm', following name-value arguments are supported:
%
%       'Alternative'
%       'DriftThreshold'
%       'InputType'
%       'WarmupPeriod'
%       'WarningThreshold'
%
%   For DETECTIONMETHOD = 'hddma', following name-value arguments are supported:
%
%       'Alternative'
%       'DriftThreshold'
%       'EstimationPeriod'
%       'InputBounds'
%       'InputType'
%       'WarmupPeriod'
%       'WarningThreshold'
%
%   For DETECTIONMETHOD = 'hddmw', following name-value arguments are supported:
%
%       'Alternative'
%       'DriftThreshold'
%       'EstimationPeriod'
%       'ForgettingFactor'
%       'InputBounds'
%       'InputType'
%       'WarmupPeriod'
%       'WarningThreshold'
%
%
%   For more details on drift detection methods, see reference page for <a href="matlab:doc incrementalConceptDriftDetector">incrementalConceptDriftDetector</a>.
%
%   Example 1: Generate random bit stream and monitor for any changes.
%
%     % Set random seed for reproducibility
%     rng(0)
%     numObservations = 3000;
%     switchPeriod = 1000;
%     detector = incrementalConceptDriftDetector('ddm');
%     % Value of 1 indicates a failure.
%     % For the first 1000 observations, failure rate is 0.1.
%     % After 1000, failure rate increases to 0.6.
%     for i = 1:numObservations
%         if i <= switchPeriod
%             failurerate = 0.1;
%         else
%             failurerate = 0.6;
%         end
%         X = rand()<failurerate;
%         detector = detectdrift(detector,X);
%         if detector.DriftDetected
%             sprintf("Drift detected at Observation #%d. Detector reset.",i)
%             detector = reset(detector);
%         elseif detector.WarningDetected
%             sprintf("Warning detected at Observation #%d",i)
%         end
%     end
%
%   See also incremental.drift.DriftDetectionMethod, incremental.drift.DriftDetectionMethod.detectdrift,  
%            incremental.drift.HoeffdingDriftDetectionMethod, incremental.drift.HoeffdingDriftDetectionMethod.detectdrift. 

% References:
%
%   [1] Gama, J., Medas, P., Castillo, G., & Rodrigues, P. (2004, September).
%       Learning with drift detection. In Brazilian symposium on artificial
%       intelligence (pp. 286-295). Springer, Berlin, Heidelberg.
%
%   [2] Frias-Blanco, I., del Campo-Ávila, J., Ramos-Jimenez, G., Morales-Bueno, R., Ortiz-Diaz, A.,
%       Caballero-Mota, Y. (2014). Online and non-parametric drift detection methods based on Hoeffding's bounds.
%       IEEE Transactions on Knowledge and Data Engineering, 27(3), 810-823.

%   Copyright 2021-2022 The MathWorks Inc.

arguments
    DetectionMethod {mustBeTextScalar(DetectionMethod)} = ''
end

arguments (Repeating)
    varargin
end

[DriftMethods, DriftConstructors, DefaultMethod] = incremental.drift.utils.DriftMethodsList();

if isempty(DetectionMethod)
    driftmethod = DefaultMethod;
else
    driftmethod = validatestring(DetectionMethod,lower(DriftMethods),mfilename,'DetectionMethod');
    driftmethod = upper(driftmethod);
end

varargin = incremental.drift.utils.ModifyInputs(driftmethod,varargin{:});

DriftDetector = incremental.drift.ConceptDriftDetector.make(DriftConstructors{ismember(DriftMethods,driftmethod)},varargin{:});

end