function [obj, data] = generateFakeData(m, con, outputs, times, errorFunc, nonNegMeasurements, populate, seed, opts)
%function [obj, data] = generateFakeData(m, con, outputs, times, errorFunc, nonNegMeasurements, populate, seed, opts)

if nargin < 9
    opts = [];
    if nargin < 8
        seed = [];
        if nargin < 7
            populate = [];
            if nargin < 6
                nonNegMeasurements = [];
            end
        end
    end
end

if isempty(nonNegMeasurements)
    nonNegMeasurements = true;
end
if isempty(populate)
    populate = true;
end

% Apply random stream
defaultStream = RandStream.getDefaultStream();
if ~isempty(seed)
    randStream = RandStream('mt19937ar', 'Seed', seed);
else
    randStream = defaultStream;
end
randState = randStream.State;

% Generate simulation
if populate
    sim = Simulate(m,con,opts);
end

ny = length(outputs);
nt = length(times);

outputList = zeros(ny*nt,1);
timesList = zeros(ny*nt,1);
if populate
    measurements = zeros(ny*nt,1);
end

for i = 1:ny
    for j =1:nt
        ind = (i-1)*nt+j;
        outputList(ind) = outputs(i);
        timesList(ind) = times(j);
        
        if populate
            C = m.c(outputs(i),:);
            x = deval(sim.sol,times(j));
            y = C*x;
            sd = errorFunc(times(j), outputs(i), y);
            if nonNegMeasurements
                measurements(ind) = max(y + sd*randn(randStream), 0);
            else
                measurements(ind) = y + sd*randn(randStream);
            end
        end
    end
end

if populate
    obj = constructObjectiveChiSquare(m, outputList, timesList, errorFunc, nonNegMeasurements, measurements, false);
else
    obj = constructObjectiveChiSquare(m, outputList, timesList, errorFunc, nonNegMeasurements);
end

RandStream.setDefaultStream(defaultStream);

if nargout >= 2
    data.Outputs            = outputs;
    data.Times              = times;
    data.OutputList         = outputList;
    data.TimesList          = timesList;
    data.ErrorFunction      = errorFunc;
    data.Measurements       = measurements;
    data.RandStream.Stream  = randStream;
    data.RandStream.State   = randState;
end

end