function G = computeObj(m, con, obj, opts)
% G = computeObj(m, con, obj, opts)
% This function computes the total objective function value for a vector of
% con and a matrix of obj.
verboseAll = max(opts.Verbose-1,0);

% Constants
nX = m.nX;
nCon = length(con);
nObj = size(obj,2);

% Initialize variables
G = 0;
intOpts = opts;

if opts.Verbose; disp('Integrating forward...'); end
for iCon = 1:nCon
    if verboseAll; tic; end
    
    % Modify opts structure
    intOpts.AbsTol = opts.AbsTol{iCon};
    intOpts.ObjWeights = opts.ObjWeights(iCon,:);
    intOpts.tGet = opts.tGet{iCon};
    
    % Integrate
    if opts.continuous(iCon) && opts.complex(iCon)
        sol = integrateObj(m, con(iCon), obj(iCon,:), intOpts);
    elseif opts.complex(iCon)
        sol = integrateSys(m, con(iCon), intOpts);
    elseif opts.continuous(iCon)
        sol = integrateObjDisc(m, con(iCon), obj(iCon,:), intOpts);
    else
        sol = integrateSysDisc(m, con(iCon), intOpts);
    end
    
    % Extract continuous term
    if opts.continuous(iCon)
        contG = sol.y(nX+1,end);
    else
        contG = 0;
    end
    
    % Compute discrete term
    discG = 0;
    for iObj = 1:nObj
        iDiscG = obj(iCon,iObj).G([], sol, con(iCon).u, 1);
        discG = discG + opts.ObjWeights(iCon,iObj) * iDiscG;
    end
    
    % Add to cumulative goal value
    G = G + contG + discG;
    
    if verboseAll; fprintf('iCon = %d\tG = %g\tTime = %0.2f\n', iCon, contG + discG, toc); end
end

if opts.Verbose; fprintf('Summary: G = %g\n', G); end
