function [result,dataPerBeat] = ait_challenge_2(recordName,pars,model)
%
% Sample entry for the 2017 PhysioNet/CinC Challenge.
%
% INPUTS:
% recordName: string specifying the record name to process
%
% OUTPUTS:
% classifyResult: integer value where
%                     N = normal rhythm
%                     A = AF
%                     O = other rhythm
%                     ~ = noisy recording (poor signal quality)
%
% To run your entry on the entire training set in a format that is
% compatible with PhysioNet's scoring enviroment, run the script
% generateValidationSet.m
%
% The challenge function requires that you have downloaded the challenge
% data 'training_set' in a subdirectory of the current directory.
%    http://physionet.org/physiobank/database/challenge/2017/
%
% This dataset is used by the generateValidationSet.m script to create
% the annotations on your training set that will be used to verify that
% your entry works properly in the PhysioNet testing environment.
%
%
% Version 1.0
%
%
% Written by: Chengyu Liu and Qiao Li January 20 2017
%             chengyu.liu@emory.edu  qiao.li@emory.edu
%
% Last modified by:
%
%


if nargin<2
    pars=get_pars(300);
end

if nargin<1
    recordName='D:\data\cinc2017\_raw\A00001';% N
end

classifyResult = 'N'; % default output normal rhythm

recNr=eval(recordName(end-4:end));

resultsFileName=[recordName,'.',mfilename]; % store results in a file with the name of the present function as the extension
if exist(resultsFileName) & 0
    fprintf(' ... loading results for signal "%s" ...\r',resultsFileName);
    load(resultsFileName,'-mat'); % supposed to yield all needed results
else
    fprintf(' ... (re)computing "%s" ...\r',resultsFileName);
    
    
    %% Load Signals
    [tm,ecg,fs,siginfo]=rdmat(recordName);
    
    %% Remove spikes
    %ecg_filtered=spike_filter(ecg);
    % ecg=schmidt_spike_removal(ecg,fs);
    % subplot(211), plot(ecg)
    %ecg_filtered=spike_filter(ecg);
    
    % subplot(212), plot(ecg_filtered)
    
    
    
    % remove first 5 s of signal - keine Verbesserung (noise wird schlechter)...
    % ecg=ecg(5*fs:end);
    
    %% QRS Detection default
    [QRS,sign,en_thres] = qrs_detect2(ecg',0.25,0.6,fs);
    
    
    %% Flip signal in case of lead inversion
    %     if sign<=0
    %         ecg=ecg*-1;
    %     end
    
    %% QRS Detection AIT
    [QRS2a,amps,qrs_widths,qrs_res]=detectevents_cinc2017(ecg,fs,pars);
    
    %% Correlation Classification
    [classes,templates]=corrclass_cinc2017(ecg,QRS2a,fs,pars.corrclass.scw1,pars.corrclass.ccmin1);
    
    %% Refine QRS complexes based on classes
    QRS2=refineQRS(ecg,QRS2a,classes,templates,fs,pars.corrclass.scw1);
    
    %% Re-calculate correlation classification with refined QRS complexes
    classes=corrclass_cinc2017(ecg,QRS2,fs,pars.corrclass.scw1,pars.corrclass.ccmin1);
    cc_res.perc_sc1_95=length(find(classes>1))/length(classes)*100;
    
    classes2=corrclass_cinc2017(ecg,QRS2,fs,pars.corrclass.scw2,pars.corrclass.ccmin2);
    cc_res.perc_sc1_98=length(find(classes2>1))/length(classes2)*100;
    
    % GSc 2017-06-11 get rid of any unstable sequences longer than 5 events
    n_different_in_a_row_min=[2:10];
    s_95=diff(classes)~=0;
    different_in_a_row_95_cumsum=cumsum(s_95).*s_95;
    I_end = find(diff(s_95)==-1);
    I_start = find(diff(s_95)==1)+1;
    if numel(I_end) > numel(I_start)
        I_start = [1 I_start]; % prepend 1 to start indices, assuming that the start of the first unstable sequence was lost
    elseif numel(I_end) < numel(I_start)
        I_end = [I_end numel(s_95)]; % append length of s to end indices, assuming that the end of the last unstable sequence was lost
    elseif numel(I_start)==1 & I_start > I_end % a single sequence of not different events embedded in disturbances
        I_start = [1 I_start]; % prepend 1 to start indices, assuming that the start of the first unstable sequence was lost
        I_end = [I_end numel(s_95)]; % append length of s to end indices, assuming that the end of the last unstable sequence was lost
    end
    different_in_a_row_95 = different_in_a_row_95_cumsum(I_end) - different_in_a_row_95_cumsum(I_start);
    cc_res.n_different_in_a_row_95_MAX=max(different_in_a_row_95); % maximum number of different classes in a row
    for i=1:numel(n_different_in_a_row_min)
        n_different_in_a_row_95_min_i=n_different_in_a_row_min(i);
        var_name_i=['n_different_in_a_row_95_min_',int2str(n_different_in_a_row_95_min_i)];
        eval([var_name_i,'=sum(different_in_a_row_95 > n_different_in_a_row_95_min_i);']); % number of sequences with at least n_different_in_a_row_min
        cc_res.(var_name_i)=eval(var_name_i); % number of sequences with at least n_different_in_a_row_min
    end
    
    % blank out long such sequences
    II=find(different_in_a_row_95>3);
    classes_blank=classes;
    for i=1:numel(II)
        classes_blank(I_start(II(i)):I_end(II(i)))=nan;
    end
    classes=classes_blank;
    
    
    s_98=diff(classes2)~=0;
    different_in_a_row_98_cumsum=cumsum(s_98).*s_98;
    I_end = different_in_a_row_98_cumsum(find(diff(s_98)==-1));
    I_start = different_in_a_row_98_cumsum(find(diff(s_98)==1)+1);
    if numel(I_end) > numel(I_start)
        I_start = [1 I_start]; % prepend 1 to start indices, assuming that the start of the first unstable sequence was lost
    elseif numel(I_end) < numel(I_start)
        I_end = [I_end different_in_a_row_98_cumsum(numel(s_98))]; % append length of s to end indices, assuming that the end of the last unstable sequence was lost
    end
    different_in_a_row_98 = I_end - I_start + 1;
    cc_res.n_different_in_a_row_98_MAX=max(different_in_a_row_98); % maximum number of different classes in a row
    for i=1:numel(n_different_in_a_row_min)
        n_different_in_a_row_98_min_i=n_different_in_a_row_min(i);
        var_name_i=['n_different_in_a_row_98_min_',int2str(n_different_in_a_row_98_min_i)];
        eval([var_name_i,'=sum(different_in_a_row_98 > n_different_in_a_row_98_min_i);']); % number of sequences with at least n_different_in_a_row_min
        cc_res.(var_name_i)=eval(var_name_i); % number of sequences with at least n_different_in_a_row_min
    end
    
    cc_res.Nnotdifferent_sc_95=min([find(diff(classes)==0),round(numel(classes)*2/3)]); % keep at least last third of events
    cc_res.Nnotdifferent_sc_98=min([find(diff(classes2)==0),round(numel(classes2)*2/3)]); % keep at least last third of events
    cc_res.Nnotdifferent_sc_min = min(cc_res.Nnotdifferent_sc_95,cc_res.Nnotdifferent_sc_98);
    if 0 % GSc 2017-06-06
        if cc_res.Nnotdifferent_sc_min > 1 && 0 % get rid of initial sequence with all different classes
            QRS2=QRS2(cc_res.Nnotdifferent_sc_min:end);
            amps=amps(cc_res.Nnotdifferent_sc_min:end);
            qrs_widths=qrs_widths(cc_res.Nnotdifferent_sc_min:end);
            
            classes=corrclass_cinc2017(ecg,QRS2,fs,pars.corrclass.scw1,pars.corrclass.ccmin1);
            cc_res.perc_sc1_95=length(find(classes>1))/length(classes)*100;
            
            classes2=corrclass_cinc2017(ecg,QRS2,fs,pars.corrclass.scw2,pars.corrclass.ccmin2);
            cc_res.perc_sc1_98=length(find(classes2>1))/length(classes2)*100;
        end
    end
    
    %% Get Averaged Beat
    [av_res,avbeats]=avbeat_cinc2017(ecg,QRS2,classes,fs,pars);
    
    %% Rhythm Classification
    [types,rhythm_res]=rhythmclass_cinc2017(ecg,QRS2,classes,amps,qrs_widths,fs,pars,avbeats);
    
    
    %% Save Averaged Beats
    % GSc 2017-05-21 - no longer needed is part of the res file now
    %    save([recordName,'_avbeats.mat'],'avbeats','-mat')
    
    
    %% Remove Averaged Beat
    atrial_ecg=removeaverage_cinc2017(ecg,QRS2,classes,avbeats,fs,pars);
    
    %% Detect AF
    af_res=detectaf_cinc2017(ecg,QRS2,classes,types,atrial_ecg,avbeats,fs,pars);
    
    %% Detect noise
    noise_res=isnoise_cinc2017(ecg,QRS,QRS2,classes,...
        avbeats,types,amps,qrs_widths,atrial_ecg,fs,pars);
    
    %% AF-Classficiation according to source template
    QRS2use=QRS;
    % QRS2use=QRS2;
    if length(QRS2use)>=6
        RR=diff(QRS2use')/fs;
        [OriginCount,IrrEv,PACEv,AFEv] = comput_AFEv(RR);
        af_res.AFEv = AFEv;
        af_res.OriginCount = OriginCount;
        af_res.IrrEv = IrrEv;
        af_res.PACEv = PACEv;
        
    else
        af_res.AFEv=NaN;
        af_res.OriginCount = NaN;
        af_res.IrrEv = NaN;
        af_res.PACEv = NaN;
    end
    
    if af_res.P_amplitude<=0.01 || isnan(af_res.P_amplitude)
        af_res.pWaveAbsence=1;
    elseif af_res.P_amplitude>0.01
        af_res.pWaveAbsence=0;
    else
        af_res.pWaveAbsence=-1;
    end
    if af_res.P_amplitude2<=0.01 || isnan(af_res.P_amplitude)
        af_res.pWaveAbsence2=1;
    elseif af_res.P_amplitude2>0.01
        af_res.pWaveAbsence2=0;
    else
        af_res.pWaveAbsence2=-1;
    end
    
    %% Combine data per beat in a dataset
    dataPerBeat=dataset;
    dataPerBeat.RecID=ones(size(QRS2'))*recNr;
    dataPerBeat.BeatID=[1:length(QRS2)]';
    dataPerBeat.BCI=[NaN;diff(QRS2)'];
    dataPerBeat.QRS=QRS2';
    dataPerBeat.amp=amps;
    dataPerBeat.width=qrs_widths;
    dataPerBeat.corrClass95=classes';
    dataPerBeat.corrClass98=classes2';
    dataPerBeat.rhythmClass=types';
    
    if 0
        %% Write results to a txt-file
        cell_data={...
            recNr,...
            qrs_res.dd,...
            qrs_res.n_not_sel,...
            qrs_res.iqr_qrs,...
            qrs_res.qrs_range,...
            cc_res.perc_sc1_95,...
            cc_res.perc_sc1_98,...
            rhythm_res.hrtrt,...
            rhythm_res.Nscs,...
            rhythm_res.majorel,...
            rhythm_res.otherel,...
            rhythm_res.sc_2,...
            rhythm_res.sc_3,...
            rhythm_res.n_premajure,...
            rhythm_res.NPa,...
            rhythm_res.NPv,...
            rhythm_res.NPc,...
            rhythm_res.NPz,...
            rhythm_res.NPp,...
            rhythm_res.NPs,...
            rhythm_res.rcopa,...
            rhythm_res.perc_premajure,...
            rhythm_res.perc_regular,...
            rhythm_res.n_hist,...
            rhythm_res.n_hist2,...
            rhythm_res.hist_gap,...
            rhythm_res.n_amps,...
            rhythm_res.n_widths,...
            rhythm_res.hr1,...
            rhythm_res.nBeats,...
            rhythm_res.hr2,...
            rhythm_res.hr_diff,...
            rhythm_res.stds,...
            rhythm_res.iqrs,...
            rhythm_res.ratioFast120,...
            rhythm_res.ratioFast100,...
            rhythm_res.ratioFast90,...
            rhythm_res.ratioFast80,...
            rhythm_res.ratioFast70,...
            rhythm_res.ratioFast60,...
            rhythm_res.ratioSlow60,...
            rhythm_res.ratioSlow55,...
            rhythm_res.ratioSlow50,...
            rhythm_res.ratioSlow45,...
            rhythm_res.range10_90,...
            rhythm_res.range5_95,...
            rhythm_res.ratioRegular3,...
            rhythm_res.ratioRegular5,...
            rhythm_res.ratioRegular10,...
            rhythm_res.ratioRegular20,...
            rhythm_res.ratioRegular10_bestPart,...
            rhythm_res.ratioRegular10_worstPart,...
            rhythm_res.ratioRegular10_PartDiff,...
            rhythm_res.nRPDR,...
            rhythm_res.nRPPR,...
            rhythm_res.nDDPP,...
            rhythm_res.nRPPDDR,...
            rhythm_res.nRPPDR,...
            rhythm_res.nRPRP,...
            rhythm_res.nPatternMax,...
            rhythm_res.nPatternSum,...
            rhythm_res.ratio_RPDR,...
            rhythm_res.ratio_RPPR,...
            rhythm_res.ratio_DDPP,...
            rhythm_res.ratio_RPPDDR,...
            rhythm_res.ratio_RPPDR,...
            rhythm_res.ratio_RPRP,...
            rhythm_res.ratioPatternMax,...
            rhythm_res.ratioPatternSum,...
            rhythm_res.iqr_irreg_RRs,...
            rhythm_res.n_hist_50,...
            rhythm_res.n_hist_20,...
            rhythm_res.n_hist,...
            rhythm_res.hist_n_diag,...
            rhythm_res.hist_ratio_diag,...
            rhythm_res.hr1_c1,...
            rhythm_res.nBeats_c1,...
            rhythm_res.hr2_c1,...
            rhythm_res.hr_diff_c1,...
            rhythm_res.stds_c1,...
            rhythm_res.iqrs_c1,...
            rhythm_res.ratioFast120_c1,...
            rhythm_res.ratioFast100_c1,...
            rhythm_res.ratioFast90_c1,...
            rhythm_res.ratioFast80_c1,...
            rhythm_res.ratioFast70_c1,...
            rhythm_res.ratioFast60_c1,...
            rhythm_res.ratioSlow60_c1,...
            rhythm_res.ratioSlow55_c1,...
            rhythm_res.ratioSlow50_c1,...
            rhythm_res.ratioSlow45_c1,...
            rhythm_res.range10_90_c1,...
            rhythm_res.range5_95_c1,...
            rhythm_res.ratioRegular3_c1,...
            rhythm_res.ratioRegular5_c1,...
            rhythm_res.ratioRegular10_c1,...
            rhythm_res.ratioRegular20_c1,...
            rhythm_res.ratioRegular10_bestPart_c1,...
            rhythm_res.ratioRegular10_worstPart_c1,...
            rhythm_res.ratioRegular10_PartDiff_c1,...
            rhythm_res.nRPDR_c1,...
            rhythm_res.nRPPR_c1,...
            rhythm_res.nDDPP_c1,...
            rhythm_res.nRPPDDR_c1,...
            rhythm_res.nRPPDR_c1,...
            rhythm_res.nRPRP_c1,...
            rhythm_res.nPatternMax_c1,...
            rhythm_res.nPatternSum_c1,...
            rhythm_res.ratio_RPDR_c1,...
            rhythm_res.ratio_RPPR_c1,...
            rhythm_res.ratio_DDPP_c1,...
            rhythm_res.ratio_RPPDDR_c1,...
            rhythm_res.ratio_RPPDR_c1,...
            rhythm_res.ratio_RPRP_c1,...
            rhythm_res.ratioPatternMax_c1,...
            rhythm_res.ratioPatternSum_c1,...
            rhythm_res.iqr_irreg_RRs_c1,...
            rhythm_res.n_hist_50_c1,...
            rhythm_res.n_hist_20_c1,...
            rhythm_res.n_hist_all_c1,...
            rhythm_res.hist_n_diag_c1,...
            rhythm_res.hist_ratio_diag_c1,...
            rhythm_res.hr1_diff,...			TODO: Remove all diff-Vars except hist_n_diag_diff
            rhythm_res.nBeats_diff,...
            rhythm_res.hr2_diff,...
            rhythm_res.hr_diff_diff,...
            rhythm_res.stds_diff,...
            rhythm_res.iqrs_diff,...
            rhythm_res.ratioFast120_diff,...
            rhythm_res.ratioFast100_diff,...
            rhythm_res.ratioFast90_diff,...
            rhythm_res.ratioFast80_diff,...
            rhythm_res.ratioFast70_diff,...
            rhythm_res.ratioFast60_diff,...
            rhythm_res.ratioSlow60_diff,...
            rhythm_res.ratioSlow55_diff,...
            rhythm_res.ratioSlow50_diff,...
            rhythm_res.ratioSlow45_diff,...
            rhythm_res.range10_90_diff,...
            rhythm_res.range5_95_diff,...
            rhythm_res.ratioRegular3_diff,...
            rhythm_res.ratioRegular5_diff,...
            rhythm_res.ratioRegular10_diff,...
            rhythm_res.ratioRegular20_diff,...
            rhythm_res.ratioRegular10_bestPart_diff,...
            rhythm_res.ratioRegular10_worstPart_diff,...
            rhythm_res.ratioRegular10_PartDiff_diff,...
            rhythm_res.nRPDR_diff,...
            rhythm_res.nRPPR_diff,...
            rhythm_res.nDDPP_diff,...
            rhythm_res.nRPPDDR_diff,...
            rhythm_res.nRPPDR_diff,...
            rhythm_res.nRPRP_diff,...
            rhythm_res.nPatternMax_diff,...
            rhythm_res.nPatternSum_diff,...
            rhythm_res.ratio_RPDR_diff,...
            rhythm_res.ratio_RPPR_diff,...
            rhythm_res.ratio_DDPP_diff,...
            rhythm_res.ratio_RPPDDR_diff,...
            rhythm_res.ratio_RPPDR_diff,...
            rhythm_res.ratio_RPRP_diff,...
            rhythm_res.ratioPatternMax_diff,...
            rhythm_res.ratioPatternSum_diff,...
            rhythm_res.iqr_irreg_RRs_diff,...
            rhythm_res.n_hist_50_diff,...
            rhythm_res.n_hist_20_diff,...
            rhythm_res.n_hist_all_diff,...
            rhythm_res.hist_n_diag_diff,...
            rhythm_res.hist_ratio_diag_diff,...
            rhythm_res.afOrNoise,...
            rhythm_res.afOrNormal,...
            rhythm_res.normalOrOther',...
            af_res.atrial_frequency,...
            af_res.P_amplitude,...
            af_res.P_amplitude2,...
            af_res.P_amplitude2rel,...
            af_res.rr_irregularity,...
            af_res.rr_irregularity2,...
            af_res.atrial_hr1,...
            af_res.atrial_hr2,...
            af_res.atrial_amp,...
            af_res.atrial_peak_var,...
            af_res.atrial_hr_ratio50,...
            av_res.av_QRS_width,...
            av_res.av_QRS_amp,...
            af_res.av_P_rel_atrial_amp,...
            af_res.AFEv,...
            af_res.OriginCount,...
            af_res.IrrEv,...
            af_res.PACEv,...
            av_res.av_cls2,...
            av_res.av1corr2,...
            av_res.av2corr2,...
            av_res.av3corr2,...
            av_res.av4corr2,...
            av_res.av_cls2,...
            av_res.av1corr2,...
            av_res.av2corr2,...
            av_res.av3corr2,...
            av_res.av4corr2,...
            af_res.pWaveAbsence,...
            af_res.pWaveAbsence2,...
            noise_res.mean_HR,...
            noise_res.max_pause,...
            noise_res.ratio_constant,...
            noise_res.ratio_ok,...
            noise_res.ratio_qrs_different,...
            noise_res.ratio_qrs_outof_amp,...
            noise_res.ratio_qrs_outof_width,...
            noise_res.ratio_samples_outof_amp,...
            noise_res.ratio_spikes,...
            noise_res.atrial_ratio,...
            noise_res.ratio_avbeat_constant_1,...
            noise_res.ratio_avbeat_constant_2,...
            noise_res.av12corr,...
            noise_res.n_classes_1_beat,...
            noise_res.sum_factor,...
            noise_res.n_over_th,...
            noise_res.ratio_avHighFreq_1,...
            noise_res.av_qrs_rest_ratio_1,...
            noise_res.ratio_avHighFreq_2,...
            noise_res.av_qrs_rest_ratio_2};
        for i=1:6
            cell_data{end+1}=af_res.p_freq_rel(i);
        end
        for i=1:6
            cell_data{end+1}=noise_res.p_freq_rel(i);
        end
        varNames=getVarNames();
        result=cell2dataset(cell_data,'VarNames',varNames);
        save(resultsFileName,'result','dataPerBeat','avbeats');
    else
        result=[];
    end
    processedTimeStamp=now;
    save(resultsFileName);
    
end


%training mode: return dataset for record
if nargin<3
    
else
    %evaluation mode: return prediction for record based on given model
    ds=double(cell2dataset(cell_data,'VarNames',varNames));
    %TODO: fix this
    load('vars2use.mat')
    
    ds=ds(:,find(vars2use));
    %display(ds);
    result=predict(model,ds);
end



