function ts = dseriesA2Q(ds, method)

% INPUTS
% - ds       [dseries]    annual frequency object with n elements.
% - method   [char]       1×m array, method used for the time aggregation, possible values are:
%                            - 'equal-per-quarter',
%                            - 'cubic-spline' (for stock variables)
%                            - 'spline-sum' (for flow variables with summation constraint
%                                            i.e four quarters sum to annual value)
%
% OUTPUTS
% - ts       [dseries]    quarterly frequency object with m<n elements.

% Copyright © 2022-2025 Dynare Team
%
% This code 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 dates submodule 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 <http://www.gnu.org/licenses/>.

    if ~isequal(ds.freq,1)
        error('Conversion only allowed for annual data!')
    end

    dQ = dates(4, [ds.dates.year(1) 1]):dates(4, [ds.dates.year(end) 4]);

    tdata = NaN(dQ.ndat, ds.vobs);

    switch method
      case 'equal-per-quarter'
        counter = 1;
        for i = 1:4:dQ.ndat
            tdata(i:i+3,:) = repmat(ds.data(counter,:), [4,1]);
            counter = counter+1;
        end
      case 'cubic-spline'
        for i = 1:length(ds.name)
            dAO = get_periods();
            ids = find(dQ.year(:,1)==dAO(1),1);
            ide = find(dQ.year(:,1)==dAO(end),1,'last');
            qPoints = dAO(1):0.25:dAO(end);
            tdata(ids+3:ide,i) = spline(dAO, ds{ds.name{i}}.data, qPoints); % First three datapoints are set to NaN
        end
      case 'spline-sum'
        for i = 1:length(ds.name)
            dAO = get_periods();
            ids = find(dQ.year(:,1)==dAO(1),1);
            ide = find(dQ.year(:,1)==dAO(end),1,'last');
            % Normalise the x point to start from 0
            dAOTmp = dAO - (dAO(1));
            dAO = [dAOTmp  dAOTmp(end) + [1 2]];
            qPoints = dAO(1):0.25:dAO(end);
            % Create cumsum of the data with initial point set to 0
            dI = [0; cumsum([ds{ds.name{i}}.data; ds{ds.name{i}}.data(end)])];
            % Compute spline
            dO = spline(dAO, dI, qPoints)';
            % Compute first difference to get flow values
            dOF = dO(2:end) - dO(1:end-1);
            % Construct the final data
            tdata(:,i) = dOF(ids:ide);
        end
      otherwise
        error('Unknow method.')
    end

    ts = dseries(tdata, dQ, ds.name, ds.tex);

    function dAO = get_periods()
        dAO = firstobservedperiod(ds{ds.name{i}}).year(1):lastobservedperiod(ds{ds.name{i}}).year(1);
    end


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

    %@test:1
    ds = dseries(randn(10,2), '2000Y');

    try
        ts = dseriesA2Q(ds, 'equal-per-quarter');
        t(1) = true;
    catch
        t(1) = false;
    end

    if t(1)
        t(2) = ts.vobs==2;
        t(3) = ts.nobs==40;
        t(4) = ts.dates(1)==dates('2000Q1');
    end

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


    %@test:2
    ds = dseries(randn(10,2), '2000Y');

    try
        ts = dseriesA2Q(ds, 'cubic-spline');
        t(1) = true;
    catch
        t(1) = false;
    end

    if t(1)
        t(2) = ts.vobs==2;
        t(3) = ts.nobs==40;
        t(4) = ts.dates(1)==dates('2000Q1');
    end

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


    %@test:3
    ds = dseries(randn(10,2), '2000Y');

    try
        ts = dseriesA2Q(ds, 'spline-sum');
        t(1) = true;
    catch
        t(1) = false;
    end

    if t(1)
        t(2) = ts.vobs==2;
        t(3) = ts.nobs==40;
        t(4) = ts.dates(1)==dates('2000Q1');
    end

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

end
