function [delays_Macro,delays_u,delays_n] = Macro_Optimal_Decoder(x,u,k,M,T,Channel)
u1 = mod(u,x); % u = u0x + u1;
u0 = (u - u1)/x;
if u0+1 == M-u0;
    n1 = x/2 - u1;
else
    n1 = x - u1; % n = 2n1 + (M-2u0-2)x = Mx - 2u;
end

preChannel = zeros(1,M*T);
postChannel = zeros(1,M*T+M-mod(length(Channel),M));
Conc_Channel = [preChannel Channel postChannel];
%delays_u = zeros(1,length(Conc_Channel));
delays_u = (T+1) * Conc_Channel;
%delays_n = zeros(1,length(Conc_Channel));
delays_n = (T+1) * Conc_Channel;
n_Erasures = 0;
u_Erasures = 0;
pn_Available = 0;
pu_Available = 0;
u_Stream = zeros(1,length(Conc_Channel));
n_Stream = zeros(1,length(Conc_Channel));

for index = T+1:length(Conc_Channel)/M;
    Current_Macro = Conc_Channel((index-1)*M+1:index*M);
    u_Stream((index-1)*M+1:(index-1)*M+u0+1) = Current_Macro(1:u0+1);
    current_u_Erasures = sum(Current_Macro(1:u0+1).*[x*ones(1,u0) u1]);
    current_pu_Available = k*(M-sum(Current_Macro));
    %current_u_Erasures = x*sum(Current_Macro(1:u0)) + u1*Current_Macro(u0+1);
    n_Stream((index-1)*M+u0+1:(index-1)*M+M-u0) = Current_Macro(u0+1:M-u0);
    current_n_Erasures = x*sum(Current_Macro(u0+2:M-u0-1)) + n1*Current_Macro(u0+1) + n1*Current_Macro(M-u0);
    if sum(Current_Macro) == 0;
        if u_Erasures == 0;
        else
            pu_Available = pu_Available + current_pu_Available;
            if pu_Available >= u_Erasures;
                delays_u(find(u_Stream(1:index*M) == 1)) = index - ceil(find(u_Stream(1:index*M) == 1)/M);
                u_Erasures = 0;
                u_Stream(1:index*M) = 0;
            end
        end
        if n_Erasures == 0;
        else
            current_pn = Current_Macro(M-u0:M);
            corresponding_us = fliplr(u_Stream((index-T-1)*M+1:(index-T-1)*M+u0+1));
            pn_Available = pn_Available + sum((-or(current_pn,corresponding_us)+1).*[u1 x*ones(1,u0)]);
        end
    else
        pu_Available = pu_Available + current_pu_Available;
        u_Erasures = u_Erasures + current_u_Erasures;
        if pu_Available >= u_Erasures;
            delays_u(u_Stream == 1) = index - ceil(find(u_Stream(1:index*M) == 1)/M);
            u_Erasures = 0;
            u_Stream(1:index*M) = 0;
        end
        n_Erasures = n_Erasures + current_n_Erasures;
        current_pn = Current_Macro(M-u0:M);
        corresponding_us = fliplr(u_Stream((index-T-1)*M+1:(index-T-1)*M+u0+1));
        pn_Available = pn_Available + sum((-or(current_pn,corresponding_us)+1).*[u1 x*ones(1,u0)]);
    end
    if pn_Available >= n_Erasures;
        delays_n(n_Stream == 1) = index - ceil(find(n_Stream(1:index*M) == 1)/M);
        pn_Available = 0;
        n_Erasures = 0;
        n_Stream(1:index*M) = 0;
        delays_u((index-T-1)*M+find(fliplr(Current_Macro(M-u0:M)) == 0)) = T;
        u_Stream((index-T-1)*M+find(fliplr(Current_Macro(M-u0:M)) == 0)) = 0;
        %Conc_Channel((index-T-1)*M+1:(index-T-1)*M+M) = -(sum(fliplr(Current_Macro(M-u0:M)))==0)+1;
        %if Current_Macro(M-u0:M) == 0;
        %    delays_u((index-T-1)*M+1:(index-T-1)*M+u0+1) = T;
        %end
    end
end
%Conc_Channel = Conc_Channel(length(preChannel)+1:length(Conc_Channel)-length(postChannel));
delays_u = delays_u(length(preChannel)+1:length(Conc_Channel)-length(postChannel));
delays_n = delays_n(length(preChannel)+1:length(Conc_Channel)-length(postChannel));
if mod(length(delays_u),M) ~= 0;
    delays_u = [delays_u T*ones(1,M-mod(length(delays_u),M))];
    delays_n = [delays_n T*ones(1,M-mod(length(delays_n),M))];
end
delays_Macro = 0;
for index = 1:length(delays_u)/M;
    delays_Macro(index) = max([delays_u((index-1)*M+1:(index-1)*M+u0+1) delays_n((index-1)*M+u0+1:(index-1)*M+M-u0)]);
end
%delays_Macro = delays_Macro(T+1:length(Conc_Channel)/M-T);