function [Xt, info] = DCFW(gradf, subgradg, lmo, maxit, tol_outer, x0)
%DCFW Summary of this function goes here
%   Detailed explanation goes here

Xt = x0;
tk = 0;
exitflag = 0;
beta = 0.8;

% initialize counters
counter_lmo = 0;
counter_gradf = 0;
counter_subgradg = 0;
timer = tic;

Gt = subgradg(Xt);
counter_subgradg = counter_subgradg + 1;

Ft = gradf(Xt);
counter_gradf = counter_gradf + 1;
Ht = Ft - Gt;

St = lmo(Ht);
counter_lmo = counter_lmo + 1;

Dt = St - Xt;
gap = - Ht(:)'*Dt(:);

tol_inner = beta * gap;
% tol_outer = 0;
% gap0 = 0.01*gap;

for t = 1:maxit

    % Gt = subgradg(Xt);    % We already compute this in the previous
    % iteration to compute gap, so we can reuse it

    for k = 1:1e7

        tk = tk + 1; % increment the total iteration counter

        if k == 1
            Xtk = Xt;
            Htk = Ht;
            Stk = St;
            Dtk = Dt;
            Ftk = Ft;
            gap_tk = gap;
        else
            Ftk = gradf(Xtk);
            counter_gradf = counter_gradf + 1;
            Htk = Ftk - Gt;

            Stk = lmo(Htk);
            counter_lmo = counter_lmo + 1;

            Dtk = Stk - Xtk;
            gap_tk = - Htk(:)'*Dtk(:);
        end

        info.inner.t(tk) = t;
        info.inner.k(tk) = k;
        info.inner.counter_lmo(tk) = counter_lmo;
        info.inner.counter_gradf(tk) = counter_gradf;
        info.inner.counter_subgradg(tk) = counter_subgradg;
        info.inner.gap_tk(tk) = gap_tk;
        info.inner.gap_tk_DC(t) = gap_tk;
        info.inner.time(tk) = toc(timer);

        % Display progress every t iteration
        %         if mod(tk, 100) == 0
        %             fprintf('t: %d, tk: %d, gap: %.6f, grad: %d, lmo: %d, subgrad: %d\n', ...
        %                 t, tk, min(info.gap_tk), counter_gradf, counter_lmo, counter_subgradg);
        %         end

        if tk >= maxit
            exitflag = 1;
            break;
        end

        eta = 2/(tk+1);

        % Line-search step-size
        %         termA = Gt(:)'*Dtk(:) - Dtk(:)'*Ftk(:) ;
        %         termB = norm ( gradf(Dtk) , 'fro')^2;
        %         eta = termA / termB;
        %         eta = min(eta, 1);
        %         eta = max(eta, 0);
% 
%                 top = top + gap_tk^2;
%                 eta = gap_tk/sqrt(top);

        % Demyanov-Rubinov step-size
%         eta = min(gap_tk/(Ls*norm(Dtk,'fro')^2), 1);

        Xtk = Xtk + eta*Dtk;

        %         if gaptk <= gap0/t
        if gap_tk <= tol_inner
            break;
        end

    end


    Xt = Xtk;
    Gt = subgradg(Xt);
    counter_subgradg = counter_subgradg + 1;

    Ft = gradf(Xt);
    counter_gradf = counter_gradf + 1;
    Ht = Ft - Gt;

    St = lmo(Ht);
    counter_lmo = counter_lmo + 1;

    Dt = St - Xt;
    gap = - Ht(:)'*Dt(:);

    

    info.outer.counter_lmo(t) = counter_lmo;
    info.outer.counter_gradf(t) = counter_gradf;
    info.outer.counter_subgradg(t) = counter_subgradg;
    info.outer.gap(t) = gap;
    info.outer.tk(t) = tk;
    info.outer.time(t) = toc(timer);

    % Display progress every t iteration
    if mod(t, 1) == 0
        fprintf('t: %d, tk: %d, gap: %.6f, grad: %d, lmo: %d, subgrad: %d\n', ...
            t, tk, gap, counter_gradf, counter_lmo, counter_subgradg);
    end

    if exitflag
        break;
    end

    if gap <= tol_outer
        exitflag = 1;
        break;
    end

    if gap < tol_inner
        tol_inner = beta*tol_inner;
    end


end

end

