function [y,HR,GS] = gaussADAPTinter(x,t,Nskip,threshold,thresstep,gaussmin,gaussmax,edgesupport,dx,supportmlt,localpars)
%[y,HR,GS] = gaussADAPTinter(x,t,Nskip,threshold,thresstep,gaussmin,gaussmax,edgesupport,dx,supportmlt,localpars)
% GAUSSADAPTINTER prehľadáva v signále body, kde sa mení diferencia, v týchto
% bodoch rozdelí signál na časti, pre ktoré spočíta šírku gausovho okna
% Vstupy:   x - signál na filtráciu
%           t - časové údaje
%           Nskip - "obskakovanie" pri určovaní diferencie - možno voliť
%           threshold - prvá hodnota v zmenách diferencie
%           thresstep - krok, ktorým určujeme ďalšie zmeny diferencie
%           gaussmin - minimálna šírka gaussovho okna
%           gaussmax - maximálna šírka gaussovho okna
%           edgesupport - boolovská hodnota, či bude podporovať nájdené
%           body susednými, pre podporu voliť '1'
%           dx - diferencia, pokiaľ chceme použiť odhad z inej teploty
%           supportmlt - ako ďaleko podporujem susednými bodmi
%           localpars - parametre na hľadanie extrémov
% Výstupy:  y - výsledný signál po filtrácii
%           HR - vektor hraničných rozdelovacích bodov
%           GS - vektor vypočítaných gaussových okien


THRESHOLDS = [0 threshold:thresstep:1 1];       %vektor hodnôt na základe, ktorých rozhodujem, či sa derivácia mení
%natoľko, aby som pridal nový hraničný bod

%% DERIVACIA SIGNALU

if nargin < 11 %parametre na prehľadávanie extrémov:
    %po poradí ako je nižšie "localpars"
    %derivácia rovná menšia ako dané číslo
    %vzdialenosť do akej budem kontrolovať, či je tento extrém výrazný
    %hodnota ktorú musí prekročiť priemerná normalizovaná diferencia v
    %tejto oblasti
    %vzdialenosť o akú budem pridávať podporných susedných bodov
    %počet pridaných bodov na každej strane
   localpars = [1*1e-3 gaussmax 0.003 10 3]; 
end

if nargin < 10       %koeficient využívaný pri znásobovaní hraničných bodov, "ako ďaleko od hranice mám pridať ďalšie"
   supportmlt = 5; 
else
    supportmlt = ceil(supportmlt);
    if supportmlt < 2;          %je to omedzené dĺžkou minimálneho gaussovského okna gaussmin
        supportmlt = 2;
    end
end

if nargin < 9                   %ak nie je zadaná iná derivácia, vezme svoju deriváciu s možnosťou vynechávania bodov Nskip
    dx = diff(x(1:Nskip:end));
else
    Nskip = 1;
end

if nargin < 8
    edgesupport = 0; %možnosť rozhnodnutia, či bude nájdené body "podporovať" susednými
end

ndx = abs(dx)/max(abs(dx)); %normalizovanie derivácie

%% URČENIE HRANÍC FILTRÁCIE

HR = 0;

index = 1;
EXTREMS = [];           % vektor pre extrémy
for i = 1:length(ndx)
   direction = notin(THRESHOLDS(index),THRESHOLDS(index+1),ndx(i));  %ak derivácia vypadne z aktuálneho intervalu
                                            %pridám hraničný bod a upravím
                                            %tento interval pre ďalšie
                                            %pozorovanie (index ++/
                                            %index--)
   
   switch direction
       
       case 1                               %sme nad intervalom, tak interval zvýšime
           HR(end+1) = i*Nskip+1;
           index = index+1;
       case -1                              %sme pod intervalom, tak interval znížime
           HR(end+1) = i*Nskip+1;
           index = index-1;
       case 0
       
   end
   
   
   if ndx(i) < localpars(1)  %"derivácia rovná nule"
       surround = 0;
       limit = localpars(2);
       try
           for j = 1:limit
              surround = surround + ndx(i-j) + ndx(i+j); 
           end
       catch
       end
       
       surround = surround/(2*limit + 1);  %vezmem aritmetický priemer derivácii z okolia možného silného extrému
                                           %pokiaľ je táto hodnota veľká
                                           %znamená to, že sme naozaj v
                                           %silnom extréme, v extréme je
                                           %derivácia malá a okolo neho
                                           %veľká -> signál silno
                                           %stúpa/klesá
       if surround > localpars(3)
           EXTREMS(end+1) = i*Nskip+1;
       end
       
   end
   
end

%upravenie vektoru hraníc, aby bol taký, aký je potrebné... žiadne
%duplikáty, na začiatku nula, na konci koncový index signálu
HR(end+1) = length(x);
HR = unique([0 HR length(x)]) ;
dHR = diff(HR);     %dĺžky jednotlivých sekcií/intervalov

for i = 1:length(dHR)   %odstránenie blokov, ktoré nie sú dostatočne dlhé
        %ako je uvedené v práci, nechceme priveľa bodov
    if dHR(i) <= 2*gaussmin + 1
       HR(i+1) = 0;
    end
    
end

HR = [0 setdiff(HR,0)];     %odstránenie vynulovaných prvkov
if HR(end) ~= length(x)     %stávalo sa, že sa odstránil aj posledný index, tak ho musím kontrolovať
   HR(end) = length(x);  
end

dist = localpars(4); range = localpars(5);
if edgesupport              %znásobenie hraničných bodov
   NEWHR = [];
   for i = 2:length(HR)-1
      try
        
        NEWHR(end+1) = HR(i)-supportmlt*gaussmin -2;    %význam supportmlt je vysvetlený hore
        NEWHR(end+1) = HR(i);
        NEWHR(end+1) = HR(i)+supportmlt*gaussmin +2;
      catch
      end
   end
    
   NEWEXTREMS = [];     
   for i = 1:length(EXTREMS)
      try
          NEWEXTREMS(end+1) = EXTREMS(i);
          for j=1:range
            NEWEXTREMS(end+1) = EXTREMS(i)-dist*j*gaussmin -2;
            NEWEXTREMS(end+1) = EXTREMS(i)+dist*j*gaussmin +2;
          end
      catch
      end
   end
   
   %upravenie vektoru hraníc do potrebnej podoby
   HR = unique([0 NEWHR NEWEXTREMS length(x)]) ;
   HR = HR(HR>=0);
   HR = HR(HR<=length(x));
   HR = sort(HR,'ascend');
   
   HR = unique([0 HR NEWEXTREMS length(x)]) ;
   HR = HR(HR>=0);
   HR = HR(HR<=length(x));
   HR = sort(HR,'ascend');
   
   
end

dHR = diff(HR);

for i = 1:length(dHR) 
   
    if dHR(i) <= 2*gaussmin + 1
       HR(i+1) = 0;
    end
    
end

%opäť nutná kontrola
HR = [0 setdiff(HR,0)];
if HR(end) ~= length(x)
   HR(end) = length(x);  
end
HR = unique([0 HR length(x)]) ;
dHR = diff(HR);

SUMS = [];  %prírastok signálu na jednotku dĺžky
for i = 1:length(HR)-2
   SUMS(i) = sum(abs(dx(floor(HR(i)/Nskip)+1:floor(HR(i+1)/Nskip))))/dHR(i); %ZMENA S ABSOLUTNOU HODNOTOU
end
SUMS(end+1) = sum(abs(dx(floor(HR(end-1)/Nskip)+1:end)))/dHR(end); %ZMENA S ABSOLUTNOU HODNOTOU

MAXSUM = max(abs(SUMS));
NSUMS = abs(SUMS)/MAXSUM;   %normalizácia prírastkov, z nich sa určí šírka gaussovyských okien

%% URČENIE GAUSSOVSKÝCH OKIEN

GS = [];
for i = 1:length(NSUMS)
   GS(i) = floor(gaussmax + (gaussmin-gaussmax)*((NSUMS(i))^(1/1)));    %je viac možností, ako priradiť
                    % z intervalu <min;max>, je to nastavené, ako je
                    % popísané v práci, teda lineárne 1/1, dá sa voliť
                    % napríklad aj kvadraticky (1/2), kubicky (1/3)...
   if GS(i)*2 +2 > dHR(i)  %chceme aby platilo, že dĺžka signálu je rovná väčšia 2g+1
       GS(i) = floor(dHR(i)/2 -1); %celé číslo
       if GS(i)<gaussmin
           GS(i) = gaussmin-1;
       end
        
   end

end

LS = GS(1:end-1); %pridelenie, pri ktorom nemusím riešiť žiadne problémy
RS = GS(2:end);

y = gaussMULTIfiltinter(x,t,HR,GS,LS,RS);

end

function [direction] = notin(small,big,num) %pomocná funkcia pri prechádzaní diferencii

if num<small
       direction = -1;
elseif num>big
        direction = 1;
else
    direction = 0;
end

end

