function [report]=challenge_detector_TH(recordName,annName,testing)
%% Tilos detector written for Cinc2014

plotten=0;

%  metadata for the record,
%siginfo = wfdbdesc(recordName);
%description = squeeze(struct2cell(siginfo));
%description = description(5,:);
% loading signals

[tm,rawsignals,Fs]=rdsamp(recordName);
rawsignals=rawsignals';
fa=Fs;
pq=1; 
%% RESAMPLING
if(fa~=250)
        %figure; hold on ; 
      [rawsignals, pq]=resample_TH(rawsignals,250,fa); %plot(rawsignals1(1,:));
   %         rawsignals=resample(rawsignals',250,fa)'; plot(rawsignals(1,:),'r'); 
      fa=250; 
   %NN=size(rawsignals,2);  plot(linspace(1,N,NN), rawsignals(1,:),'r'); 
end
numChan=size(rawsignals,1); 
N=size(rawsignals,2); 
%% ++++++++++++++++++++++++++++++++++++++++++
% ++++++++         Preprocessing     +++++++++++++++++++
% AUSREISSERBEREINIGUNG & NORMIERUNG 
% ++++++++++++++++++++++++++++++++++++++++++

 signals =preprocess_Cinc2014(rawsignals,fa);
  
%% ###########                 check Periodicity          ########################
plotten1=0;
[signals, exp_bbi] =check_periodicity_Cinc2014(signals,fa,plotten1);
numChan=size(signals,1);

%% INITIAL DETECTION 
plotten1=0;
initial_beats=initial_detection_cinc2014_TH(signals,exp_bbi,plotten1);
%% SIMILARITIES
[simi,simis,Im,L]=calc_similarities(signals,initial_beats,exp_bbi,0); 

        if(plotten==1), figure(2);hold on;  plot(simis'*10);plot(simi*10,'r');end
mindist=round(exp_bbi/2);
beats=findpeaks_TH(simi,[1:-0.1:0.3],fa,mindist);

md=round(mean(diff(beats)));
        if(plotten==1),  plot(beats,1,'m*');end
 rbbi=diff(beats); rbbi=[rbbi(1,1), rbbi];
        if(plotten==1), fh=figure; plot(beats,rbbi,'y');end
 %%################    correct BBI     ########################
 mindist=round(exp_bbi/6);
potbeats=findpeaks_TH(simi,[1:-0.1:0.2],fa,mindist);
potbeats(2,:)=simi(1,potbeats(1,:));
beats(2,:)=simi(1,beats(1,:));
         if(plotten==1),figure(2); hold on; plot(potbeats(1,:),10*potbeats(2,:),'g+'); end% conformities
% robust mean BBI ++++++++++
x=rbbi;
for nix=1:21

mrbbi=conv([x(1,1:10), x, x(1,end+[-9:0])],ones(1,21)/21,'full');mrbbi=mrbbi(1,(10+11):(end-10-10)); 
abw_zu_gross=abs(rbbi-mrbbi)>30;
x=rbbi;
x(1,abw_zu_gross)=mrbbi(1,abw_zu_gross);
if(plotten==1) , figure(3); hold on ; plot(beats(1,:),mrbbi,'g'); end
end
temp=conv([x(1,1:15), x, x(1,end+[-14:0])],ones(1,31)/31,'full'); 
mrbbi=temp(1,31:(end-30)); 

%  +++++++++++++++++++++
 if(plotten==1),figure(fh); hold on ; plot(beats(1,:),mrbbi,'g');end
bad=abs( rbbi-mrbbi)>md/2*beats(2,:).*[1, beats(2,1:(end-1))];
bad=conv(double(bad),ones(1,7),'same')>0;
 if(plotten==1&&sum(bad,2)>0),figure(2); hold on; plot(beats(1,bad),10,'black*'); end

pbbi=[potbeats(1,2)-potbeats(1,1), diff(potbeats(1,:))];
% mrbbi (Laenge gleich der von beats) auf Laenge der potbeats anpassen
%  ( Fourier-Interpolation )
% % % % p=fit(beats(1,:)',mrbbi','linearinterp');
% % % % mpbbi=feval(p,potbeats(1,:))';

Nb=size(mrbbi,2);
if(mod(Nb,2)==0) % falls gerade Anzahl an schlaegen
    anpass=size(potbeats,2)-Nb+1; 
    f=fft(mrbbi); 
    f=[f(1, 1:(Nb/2)), zeros(1,anpass), f(1,(Nb/2+2):end)];
    mpbbi=ifft(f)*size(f,2)/Nb; 
else % ungerade Anzahl
     anpass=size(potbeats,2)-Nb; 
     f=fft(mrbbi); 
    f=[f(1, 1:((Nb+1)/2)), zeros(1,anpass), f(1,((Nb+1)/2+1):end)];
    mpbbi=ifft(f)*size(f,2)/Nb; 
end
mpbbi=real(mpbbi); 
%figure; subplot(2,1,1);plot(mrbbi);subplot(2,1,2);  plot(mpbbi); 
%% ---------          LUECKEN-FUELLUNG     ------- -----
luecke=find((pbbi-mpbbi)./mpbbi>0.6); % Luecken

if(~isempty(luecke))
     if(plotten==1)
figure(12); hold on; plot(potbeats(1,:), pbbi); 
plot(potbeats(1,:), mpbbi,'g');
plot(potbeats(1,luecke),400,'black+');
     end
 [ ~, exp_amount]=min( abs([1/2; 1/3; 1/4; 1/5; 1/6]*pbbi(1,luecke)-ones(5,1)*mpbbi(1,luecke)));
 versch=0;
 
 for k=1:size(luecke,2)
     fbeats=round(linspace(potbeats(1,luecke(1,k)-1+versch), potbeats(1,luecke(1,k)+versch) , exp_amount(1,k)+2));  fbeats=fbeats(1,2:(end-1));
     fbeats(2,:)=0.1*ones(1,exp_amount(1,k)); 
     potbeats=[potbeats(:,1:( luecke(1,k)-1+versch) ), fbeats, potbeats(:,(luecke(1,k)+versch ): end)]; 
         versch=versch+exp_amount(1,k); 
       if(plotten==1),   figure(2); hold on; plot(potbeats(1,:),5*potbeats(2,:),'+'); end
 end
end
 pbbi=[potbeats(1,2)-potbeats(1,1), diff(potbeats(1,:))];
 if(plotten==1), figure(12); hold on; plot(potbeats(1,:), pbbi,'r'); end
     a=find(diff([0,bad,0])==1);
     b=find(diff([0,bad,0])==-1);
     if(~isempty(a))
    if(a(1,1)<3), a(1)=[]; b(1)=[];end
     if(~isempty(a))
    if(b(1,end)>(size(beats,2)-2)), a(end)=[]; b(end)=[];end
     end
     end
  %% ################ lucky - picking ##########################
  versch=0; 
  cbeats=beats; 
    for kk=1:size(a,2);%s
      links=[beats(1,a(1,kk)+[-2, -1]); simi(1,beats(1,a(1,kk)+[-2, -1]))];
      rechts=[beats(1,b(1,kk)+[1, 2]); simi(1,beats(1,b(1,kk)+[1, 2]))];
      mitte=potbeats(:,potbeats(1,:)>=beats(1,a(1,kk))&potbeats(1,:)<=beats(1,b(1,kk)));
        those=[links, mitte, rechts];
        ebbi=mean([mrbbi(1,beats(1,:)==links(1,1)), mrbbi(1,beats(1,:)==links(1,1)), mrbbi(1,beats(1,:)==rechts(1,1)), mrbbi(1,beats(1,:)==rechts(1,2))]);
       
        [corrected_beats]=lucky_picking_cinc2014(those,ebbi,0);
        
        cbeats=[cbeats(:,1:(a(1,kk)+versch-3)), corrected_beats, cbeats(:,(b(1,kk)+versch+3):end)];
        eingefuegt=size(corrected_beats,2);
        ausgefuegt=(b(1,kk)+2-(a(1,kk)-2)+1);
        versch=versch+eingefuegt-ausgefuegt; 
      % figure(2); hold on; plot(cbeats(1,:), 0.3*kk*cbeats(2,:),'black+'); 
    end
           if(plotten==1), fhh=figure('Name',recordName); hold on; plot(cbeats(1,2:end), diff(cbeats(1,:))); end
           if(plotten==1),  figure(2); hold on; plot(cbeats(1,:), 7*cbeats(2,:),'black+'); end
%      those=potbeats(1,:)>=beats(1,end-4);
%         [beats]=lucky_picking_cinc2014(potbeats(:,those),md,0);
%% #########              write annotation-file            ####################
qrs=round(cbeats(1,:)/pq); 
%save([pwd,'/anno_test.mat'],'qrs'); %disp(qrs);
if(testing==0)
type=cell(size(qrs,2),1);
type(:)={'N'};
wrann(recordName,annName,qrs',type);

%disp('hat funktioniert');
end

%% JUST FOR TESTING
if(testing==1)
[ann_atr,type_atr,subtype,chan,num,comments]=rdann(recordName,'atr');
refbbi=diff(ann_atr'); refbbi=[refbbi(1,1), refbbi];
        if(plotten==1), 
            figure(fhh); hold on;
            plot(ann_atr, refbbi,'r');
        end
 [TP,FN,FP,Se,pP,Acc]=myBxb_mod(ann_atr', cbeats(1,:), 'samplingFrequency',250, 'acceptanceInterval',[150 150]);
report={recordName,TP,FN,FP,Se,pP,Acc};
else
    report=[]; 
end

end



%%##########################################################################

%##########################################################################

%##########################################################################

%##########################################################################

function [signals] =preprocess_Cinc2014(rawsignals,fa)
%fa=siginfo.SamplingFrequency;
%fa=str2num(fa(1,1:4));
%B=fir1(fa,[1, 90]/(0.5*fa),'bandpass');%signals=conv2(rawsignals,B,'same');
% just for Cinc2014
% preprocess the ecg ( 1. Channel) 
N=size(rawsignals,2); 
numChan=size(rawsignals,1);
signals=zeros(numChan, N); 
 sig_h=conv2(rawsignals(1,:),ones(1,5)/(5),'same');
 sig_l=conv2(rawsignals(1,:),ones(1,round(fa/6)*2+1)/(2*round(fa/6)+1),'same'); 

 signals(1,:)=sig_h-sig_l; 
 % preprocess the others
 sig_h=conv2(rawsignals(2:end,:),ones(1,5)/(5),'same');
 sig_l=conv2(rawsignals(2:end,:),ones(1,round(fa/2)*2+1)/(2*round(fa/2)+1),'same'); 
 signals(2:end,:)=sig_h-sig_l; 

%signals=signals(1,:); % JUST FOR TESTING

%figure; hold on; plot(signals(1,:)); figure; plot(signals(2,:));

for k=1:size(signals,1) %loop through channels
  
 %   figure; hold on; plot(x(k,:),'black'); 
    n20=round(N/20); 
    counter=0;
  for n=round(N/10):round(N/10):(N-N/10) % Stichproben 
      counter=counter+1;
      sig=signals(k,n+[-n20:n20]);
      m(1,counter)=max(abs(sig));
      %%% ca(counter,:)=xcorr(sig,sig,2*tp(1,2),'unbiased');
  end
% % %   mca=mean(ca,1); 
% % %   figure; plot(mca); 
% % %   if(mca(1,2*tp(1,2)+1+tp)>0.3*mca(1,2*tp(1,2)+1))%% Power-line-Interference
% % %       disp('PLI !!'); 
% % %   end
  
      thresh=2*median(m);
      bad=conv(double(abs(signals(k,:))>thresh),ones(1,round(fa/10)),'same')>0;
   signals(k,bad|isnan(signals(k,:)))=0; % Nullsetzen zu grosser Aussreisser
   skalier=(0.01+std(signals(k,:)));
   signals(k,:)=signals(k,:)/skalier; % normieren
% plot(signals(k,:),'b');
 end


end

function  [signals, exp_bbi] =check_periodicity_Cinc2014(signals,fa,plotten)
numChan=size(signals,1); 
N=size(signals,2); 
minbbi=round(300*fa/1000);

maxbbi=round(2000*fa/1000); 

 IL=2*maxbbi; % Subintervall-laenge, die sind variabel ( abhaengig von  expected_period)
 % so festgesetzt auf diesen Wert ( klappt nur fuer Detektion fetaler Herzschlaege !!)
ILhalf=round(IL/2); 
w=-ILhalf:ILhalf;
amount_Intervals=13;
zentren=linspace(1,N,amount_Intervals+2); % die muessen in Anzahl und Lage fuer jeweilige Intervall-laenge gleichbleibend/konstant/unabhaengig
zentren=zentren(1,2:(end-1));
exp_bbis=nan(1,numChan);


    for n=1:numChan
if(n>1&&~isnan(exp_bbis(1,1))) % JUST FOR CINC2014
    minbbi=round(0.7*exp_bbis(1,1));
    maxbbi=round(1.5*exp_bbis(1,1));
end
gthresh=exp(-0.5*(([minbbi:maxbbi]-200)/200).^2);
        for k=1:size(zentren,2)
            I=round(zentren(1,k)+w);
        s1a=conv(signals(n,I(1,:)),ones(1,31)/31,'same');
        
        ca(k,:)=xcorr(s1a,s1a,ILhalf,'unbiased');
        maxc=ca(k,ILhalf+1); 
% % %        [ mh(1,1), period(1,1)]=max(ca(k,ILhalf+[minbbi:lowermid])); 
% % %        [ mh(1,2), period(1,2)]=max(ca(k,ILhalf+[(lowermid+1):uppermid])); 
% % %        [ mh(1,3), period(1,3)]=max(ca(k,ILhalf+[(uppermid+1):maxbbi])); 
% % %        
% % %          [~, this]=max(mh); 
% % %        period(1,1)=period(1,1)+minbbi-1; 
% % %        period(1,2)=period(1,2)+lowermid-1; 
% % %        period(1,3)=period(1,3)+uppermid+1-1; 
threshold=0.9; periods=[];
while(isempty(periods)&&threshold>0.3)
bigger=double( (ca(k,ILhalf+1+[minbbi:maxbbi]).*gthresh)>threshold*maxc);
bigger(1,1)=0; bigger(1,end)=0; 
db=[diff(bigger)];
periods=round((find(db>0)+find(db<0))/2)+minbbi-1; % contains detected beats
threshold=threshold-0.05; 
end
                if(~isempty(periods))
                ebbi(1,k)=periods(1,1); % der 2. ist der naechste cross-corr-peak, der erste ist der auto-corr-peak
                else
                ebbi(1,k)=NaN; 
                end
            
        end
        if(plotten==1), figure; plot(ca'); end
      %  if(n==1); disp(ebbi); end
        num_good_Intervals(1,n)=sum(~isnan(ebbi),2);
            if(num_good_Intervals(1,n)>amount_Intervals/2)
                exp_bbis(1,n)=median(ebbi(1,~isnan(ebbi))); 
            else
                exp_bbis(1,n)=NaN; 
            end
    end

signals=signals(~isnan(exp_bbis),:);
if(~isnan(exp_bbis(1,1)))
    exp_bbi=exp_bbis(1,1);

else % if first Signals is to bad ( this case is not expected to happen in Cinc2014
    [~, temp]=max(num_good_Intervals); 
    exp_bbi=exp_bbis(1,temp); 
    [ ~, just_those]=sort(-num_good_Intervals(1,num_good_Intervals>amount_Intervals/2)  ); 
   signals=signals(just_those,:);
 
   disp([ '1. Channel is too bad !' ,num2str(just_those(1,1)), ' is taken as best channel ( for initial Detection )']); 
end

end

function initial_beats=initial_detection_cinc2014_TH(signals,exp_bbi,plotten)
numChan=size(signals,1); 
%% #############    INITIAL DETECTION  ################################
exp_amount=size(signals,2)/exp_bbi;
initial_beats=[];counter=0;
 k=1;
 Es=conv(signals(k,:).^2,ones(1,21)/21,'same'); % Energy of the Signal ( beats/qrs-complexes)
    En=conv(signals(k,:).^2,[ones(1,100),zeros(1,21),ones(1,100)]/221,'same'); % Energy of noise
    SNR(k,:)=conv(Es./(1+En),ones(1,10)/10,'same'); % plot(SNR(k,:)); 
    mSNR=conv(abs(SNR),ones(1,2001)/2001,'same'); % threshold for initial Detection 
    fakt=4;
while(counter<20&&fakt>1)
    counter=counter+1;
    
    diffrence=(size(initial_beats,2)-exp_amount);
    if(abs(diffrence)<0.1*exp_amount)
        break;
    end
    more=diffrence<0;
    
   if(more)
       fakt=fakt-0.2;
   else
        fakt=fakt+0.2;
   end
ini_thresh=fakt*mSNR; 
            if(plotten==1&&1==1)
               
             f2=figure(121); hold on; 
             h1=plot(ini_thresh,'r'); 
            for k=1:numChan
            h2=plot(signals(k,:)-k,'black'); 
            end
     
             h3=plot(SNR,'g'); 
             legend([h1,h2,h3],{'initial threshold', 'signals used for detection', 'mean SNR, averaged over channels'}); 
            end

bigger=double((SNR)>ini_thresh);bigger(1,1)=0; bigger(1,end)=0; 
db=[diff(bigger)];
initial_beats=round((find(db>0)+find(db<0))/2); % contains detected beats
         if(plotten==1&&1==1), plot(initial_beats,1,'m*'); end
end
initial_beats=initial_beats(1,initial_beats>500&initial_beats<(size(signals,2)-500));

 %m_snr_all=x(1,potbeats); % mean SNR of each single potential beats, (mean over the channels)

%% ENDE der INITIAL DETECTION
end











