function [freq, init, data, varlist] = load_csv_file_data(file)
%function [freq, init, data, varlist] = load_csv_file_data(file)
% Loads data in a csv file.
%
% INPUTS
%  o file        string, name of the csv file (with path).
%
% OUTPUTS
%  o freq        integer scalar equal to 1, 4, 12 or 52 (for annual, quarterly, monthly or weekly frequencies).
%  o init        dates object, initial date in the dataset.
%  o data        matrix of doubles, the data.
%  o varlist     cell of strings, names of the variables.
%
% REMARKS
%  The varlist output will be set only if the first line contains variable
%  names. Similarly, if the first column does not contain dates, then
%  freq will be 1 and init will be year 1.

% Copyright © 2012-2026 Dynare Team
%
% This file is part of Dynare.
%
% Dynare is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% Dynare is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with Dynare.  If not, see <https://www.gnu.org/licenses/>.

% Output initialization
freq = 1;                  % Default frequency is annual.
init = dates(1,1);         % Default initial date is year one.
varlist = [];

assert(isfile(file), ['load_csv_file_data: I can''t find file ' file '!']);

if isoctave
    % importdata() exists under Octave but as of version 10 it is MATLAB-incompatible, does
    % not handle NaN correctly, and sometimes misdetects headers.
    % csv2cell() from the io package is unfortunately limited to lines of 32768 long.
    % So we do the following:
    % - detect column and row headers by hand, by reading at most 2 lines of the file
    % - use the fast csvread() function to read the numeric data

    fid = fopen(file, 'r');

    raw_line = fgetl(fid);
    if raw_line == -1
        error('load_csv_file_data: %s is empty')
    end

    varlist = strsplit(raw_line, ',');

    raw_line = fgetl(fid);
    if raw_line == -1
        error('load_csv_file_data: no data below column headers in %s', file)
    end
    second_row = strsplit(raw_line, ',');

    withtime = false;
    if isdate(second_row{1})
        withtime = true;
        init = dates(second_row{1});
        freq = init.freq;
        if numel(varlist) < 2
            error('load_csv_file_data: no data right to row headers in %s', file)
        end
        varlist = varlist(2:end);
    end

    fclose(fid)

    data = csvread(file, 1, withtime);

    if numel(varlist) ~= size(data, 2)
        error('load_csv_file_data: number of row headers not equal to number of data columns')
    end
else
    A = importdata(file, ',');
    if ~isstruct(A)
        data = A;
        T = {};
        withvars = false;
        withtime = false;
    else
        data = A.data;
        T = A.textdata;
        % importdata() allows text only at the top and the left, so the following
        %  tests are sufficient.
        withvars = size(T, 2) >= size(data, 2);
        withtime = size(T, 1) >= size(data, 1);
    end

    if ~withvars
        error('load_csv_file_data: variable names are missing in %s', file)
    end

    varlist = T(1, 1+withtime:end);
    T = T(2:end, :);

    if withtime
        init = dates(T{1, 1});
        freq = init.freq;
    end
end

varlist = transpose(varlist);

% Remove double quotes if any
varlist = strrep(varlist,'"','');

return % --*-- Unit tests --*--

%@test:1
% Download csv file with data.
dseries_src_root = strrep(which('initialize_dseries_class'),'initialize_dseries_class.m','');

% Instantiate a dseries from the data in the csv file.
try
  d = dseries([ dseries_src_root '../tests/data/data_ca1_csv.csv' ]);
  t(1) = true;
catch
  t(1) = false;
end

if t(1)
  t(2) = dassert(d.name,{'y_obs'; 'pie_obs'; 'R_obs'; 'de'; 'dq'});
end

T = all(t);
%@eof:1
