function CodeValidity = find_new_CTU_code (Initial_CTU_Code,target_base,Search_Step)

% This function search for new CTU codes.
% To speed up the seach process, the function uses a set of itnitial
% parameters:


% Inputs: 

%             target_base: Requested base (M)
%        Initial_CTU_Code: the largest set of codes that are valid
%                           and can be used for the requestend (M) and (N)
%                           combination. These codes are valid for the 
%                           requested spatial resolution (M).
%            Search_Step: Used to define the serach intervall 
% 

% Copyright 2015 Abdelmounaime Safia
% Lats Revision January , 4, 2015


%% ------------------------------------------------------------------------
%%
if (target_base>2) && (rem(target_base,2)==0)||(target_base<2)
    fprintf('\n _________________________________________________________________________________________________________________');
    fprintf('\n \n The spectral resolution ''base'' should be equal to 2 or anny odd natural digit higher than 2');
    fprintf('\n _________________________________________________________________________________________________________________\n');
    CodeValidity=NaN;
    return;
end


%% ------------------------------------------------------------------------
%%
initia_base = Initial_CTU_Code.SpectralRes;
NBposition = Initial_CTU_Code.SpatialRes;

%% ------------------------------------------------------------------------
%%
if target_base == 2
    CodeValidity = get_exact_code(target_base,NBposition);
    return;
end

%% ------------------------------------------------------------------------
%%
if initia_base == 2
    CodeValidity = get_exact_code(3,NBposition);
    if isstruct(CodeValidity)
       Initial_CTU_Code = CodeValidity;
    else
        CodeValidity = Search_Organization_CTU_Code_Base3(Initial_CTU_Code,Search_Step);
        if isstruct(CodeValidity)            
            update_ctu_code_database(CodeValidity);
            Initial_CTU_Code = CodeValidity;
        else            
            CodeValidity=NaN;
            exit_message_CTU_serach(1);
            return;
        end
    end
end
clear CodeValidity initia_base;

%% ------------------------------------------------------------------------
%%
if length(Initial_CTU_Code.code) < target_base
    CodeValidity = Search_Organization_CTU_Code_Base_more_than3(target_base,Initial_CTU_Code,Search_Step);
elseif length(Initial_CTU_Code.code) == target_base
    CodeValidity = Initial_CTU_Code;
else
    error('Error in target and initial base');
end    


end







%% ------------------------------------------------------------------------
%%
%             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%                            Internal functions
%             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

%% ------------------------------------------------------------------------
%%
function CodeValidity=Search_Organization_CTU_Code_Base3(Initial_CTU_Code,Search_Step)
% This function finds new CTU code for any spatial resolution (N) 
% related to a spectral resolutiom M=3 

% Initialization 
NBposition = Initial_CTU_Code.SpatialRes;
InitCode = Initial_CTU_Code.code;

coderesource=get_code_resource(Initial_CTU_Code,Search_Step);

CodeValidity.valid = 0;
New_Search = 1;
it=1;
% Serach for code
while New_Search == 1 && CodeValidity.valid == 0
    CodeValidity = get_exact_code(3,NBposition);
    if isstruct(CodeValidity)
        InitCode = CodeValidity.code;
    else
        coderesource = Searchcoderesourceintegrity (InitCode,coderesource);
        if isempty(coderesource)
            CodeValidity.valid = 0;
        else
            CodeValidity = findcodeforbase3(InitCode,NBposition,coderesource,it);
        end
        if CodeValidity.valid == 0
            prompt = Yes_No_User_Response(NBposition,length(InitCode));
            it=it+1;
            if strcmp(prompt ,'Yes')
                coderesource = max(coderesource):max(coderesource)+Search_Step;
                coderesource = Searchcoderesourceintegrity (InitCode,coderesource);
            else
                New_Search = 0;
                CodeValidity = NaN;
            end
        end
    end
end
end

%% ------------------------------------------------------------------------
%%
function CodeValidity = Search_Organization_CTU_Code_Base_more_than3(target_base,Initial_CTU_Code,Search_Step)

%if target_base ~= 3  % Case of the initia_base or target base is higher than 2
% Initialization 

NBposition = Initial_CTU_Code.SpatialRes;
InitCode = Initial_CTU_Code.code;

CodeValidity.valid = 0;
New_Search = 1;
prompt='';
it=1;
    
    while (New_Search == 1) && (target_base ~=length(InitCode))
        CodeValidity = get_exact_code(length(InitCode)+2,NBposition);
        if isstruct(CodeValidity)
            InitCode = CodeValidity.code;
            Initial_CTU_Code=CodeValidity;
        else
            if isempty (prompt)
                coderesource=get_code_resource(Initial_CTU_Code,Search_Step);               
                coderesource = Searchcoderesourceintegrity (InitCode,coderesource);                
            elseif strcmp(prompt ,'Yes')
                coderesource = max(coderesource):max(coderesource)+Search_Step;
                coderesource = Searchcoderesourceintegrity (InitCode,coderesource);
                prompt='';
                it=it+1;
            end          
            
            if ~isempty (coderesource)                                                  
                CodeValidity = findcodeforbasesupto3(InitCode,NBposition,coderesource,it); 
            else
                CodeValidity.valid = 0;
            end
            
            if CodeValidity.valid == 1
                update_ctu_code_database(CodeValidity);
                Initial_CTU_Code=CodeValidity;
                InitCode = CodeValidity.code;
                it=1;
                if target_base == length(InitCode)
                    New_Search = 0;                
                end
            else
                prompt = Yes_No_User_Response(NBposition,target_base);
                
                if strcmp(prompt ,'No')                    
                    New_Search = 0;
                end                
            end
        end        
    end
end%


%% ------------------------------------------------------------------------
%%
function CodeValidity = codevaliditytest (NBposition,TextCode)
TextUnitComb = GeneralCodeCominationForTextUnit(NBposition,TextCode);
CodeValidity = somecodificationvalidity (TextCode,TextUnitComb);
end

%% ------------------------------------------------------------------------
%%
function coderesource=get_code_resource(Initial_CTU_Code,Search_Step)

NBposition=Initial_CTU_Code.SpatialRes;
InitBase = length(Initial_CTU_Code.code);
InitCode = Initial_CTU_Code.code;

if Initial_CTU_Code.SpectralRes == 2
    start_stop=get_optimum_serach_range_for_exact_base(InitBase+1,NBposition);
else
    start_stop=get_optimum_serach_range_for_exact_base(InitBase+2,NBposition);
end

if isnan(start_stop(1,1))
    start_stop(1,1)=InitCode(end)+1;
end

if isnan(start_stop(1,2))
    start_stop(1,2)=start_stop(1,1)+Search_Step;
end

coderesource=start_stop(1,1):start_stop(1,2);

end

%% ------------------------------------------------------------------------
%%
function CodeValidity = findcodeforbase3(InitCode,NBposition,coderesource,it)
% This function find codes for a case of base  = 3 starting from
% innitial base of [1 2]


steps=length(coderesource);
M = num2str(length(InitCode)+1);
N = num2str(NBposition);
it = num2str(it);
ms1=strcat ('Searching CTU codes: ',' M= ',M,' and',' N= ',N,'. Iteration (',it,')');
h = waitbar(0,ms1);


% Check code resource validity
coderesource = Searchcoderesourceintegrity (InitCode,coderesource);

j = 1;
Temp_CodeValidity.valid = 0;
while (Temp_CodeValidity.valid == 0) && (j<=length(coderesource))
    TempCode__ = cat(2,InitCode,coderesource(j));
    Temp_CodeValidity = codevaliditytest (NBposition,TempCode__);
    j = j+1;
    waitbar(j/steps);
end
close(h);
if Temp_CodeValidity.valid == 1
    disp('Valid code is found');
    [HistResol,SpatialRes] = size(Temp_CodeValidity.Combinations);
    CodeValidity.valid = Temp_CodeValidity.valid;
    CodeValidity.SpatialRes = SpatialRes;
    CodeValidity.SpectralRes = length(Temp_CodeValidity.code);
    CodeValidity.HistResol = HistResol;
    CodeValidity.code = Temp_CodeValidity.code;
else
    disp('No valid code is found');
    [HistResol,SpatialRes] = size(Temp_CodeValidity.Combinations);
    CodeValidity.valid = 0;
    CodeValidity.SpatialRes = SpatialRes;
    CodeValidity.SpectralRes = length(Temp_CodeValidity.code);
    CodeValidity.HistResol = HistResol;
    CodeValidity.code = Temp_CodeValidity.code;
end
end

%% ------------------------------------------------------------------------
%%
function coderesource = Searchcoderesourceintegrity (InitCode,coderesource)
for i = 1:length(InitCode)
    %index_sup = find(coderesource<=InitCode(i));
    index_sup = coderesource<=InitCode(i);
    coderesource(index_sup) = [];
end
end

%% ------------------------------------------------------------------------
%%
function CodeValidity = findcodeforbasesupto3(InitCode,NBposition,coderesource,it)
% This function retrieves codes for the case of (base > 3) starting from
% innitial base. The search is performed within the interval 'coderesource'

% Check code resource validity
coderesource = Searchcoderesourceintegrity (InitCode,coderesource);
q=1;
steps=length(coderesource);
M = num2str(length(InitCode)+2);
N = num2str(NBposition);
it = num2str(it);
ms1=strcat ('Searching CTU codes: ',' M= ',M,' and',' N= ',N,'. Iteration (',it,')');
h = waitbar(0,ms1);

CodeComb = [];
TempCode = zeros(1,2);
TempCode(:) = coderesource(1:2);
CodeComb = cat(1,CodeComb,TempCode);
TempCode__ = cat(2,InitCode,TempCode);
Temp_CodeValidity = codevaliditytest (NBposition,TempCode__);
k = 2;
curcodepos = 2;
if Temp_CodeValidity.valid == 0
    while k>=1 && (Temp_CodeValidity.valid == 0)
        while (TempCode(k)~=coderesource(end)) && (Temp_CodeValidity.valid == 0)
            curcodepos = curcodepos+1;
            TempCode(k) = coderesource(curcodepos);
            CodeComb = cat(1,CodeComb,TempCode);
            TempCode__ = cat(2,InitCode,TempCode);
            Temp_CodeValidity = codevaliditytest (NBposition,TempCode__);
        end
        if Temp_CodeValidity.valid == 0
            s = 2; % positionner s à la fin du vecteur : TempCode
            i = 0;
            while ((TempCode(s) == coderesource(end)) || (TempCode(s) == coderesource(end-i)))&& (Temp_CodeValidity.valid == 0)
                s = s-1;
                i = i+1;
                if s == 0;
                    k = -1;
                    break;
                end
            end
            if k == -1
                break;
            end
            k = s;
            q=q+1;
            waitbar(q/steps)
            curcodepos = find(coderesource == TempCode(k));
            t = length(TempCode(k:end));
            TempCode(k:end) = coderesource(curcodepos+1:t+curcodepos);
            CodeComb = cat(1,CodeComb,TempCode);
            if Temp_CodeValidity.valid == 0
                TempCode__ = cat(2,InitCode,TempCode);
                Temp_CodeValidity = codevaliditytest (NBposition,TempCode__);
            end
            k = 2;
            curcodepos = find(coderesource == TempCode(k));
        end
    end
end
close(h);
% Output initialisation
[HistResol,SpatialRes] = size(Temp_CodeValidity.Combinations);
CodeValidity.valid = Temp_CodeValidity.valid;
CodeValidity.SpatialRes = SpatialRes;
CodeValidity.SpectralRes = length(Temp_CodeValidity.code);
CodeValidity.HistResol = HistResol;
CodeValidity.code = Temp_CodeValidity.code;
end

%% ------------------------------------------------------------------------
%%
function prompt = Yes_No_User_Response(N,M)
prompt = '';
while ~strcmp(prompt ,'Yes') && ~strcmp(prompt ,'No')
    prompt = '';
    fprintf('__________________________________________________________');
    fprintf('\nThere is no predifined CTU codes for this combination (N =  %d, M = %d)  !',N,M);
    fprintf('\nWould you like to perform anthoer search for the combination (N =  %d, M = %d) [Yes/No] ?',N,M);
    prompt = input(prompt,'s');
end
end

%% ------------------------------------------------------------------------
%%
