function o = add(o, param_name, varargin)

% Append a single-parameter prior to an existing @dprior object in place.
%
% Same signature as  constructor: a parameter name followed by
% name-value pairs describing the prior (shape, mean/std or h1/h2, optional
% bounds and prior_trunc). Mutates `o` in place (handle class) and returns
% it for chaining.
%
% EXAMPLE
%   Prior = dprior();
%   Prior.add('alpha', 'shape', 'beta',   'mean', 0.5, 'std', 0.1);
%   Prior.add('sig_e', 'shape', 'inv_gamma', 'mean', 0.01, 'std', 0.005);
%
% INPUTS
% - o            [@dprior]   object to extend (modified in place)
% - param_name   [char]      parameter name
% - varargin                 Path 3 name-value pairs
%
% OUTPUTS
% - o            [@dprior]   modified object (same handle)

% Copyright © 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/>.

new_p = dprior(param_name, varargin{:});
n = length(o);

o.p1   = [o.p1;   new_p.p1];
o.p2   = [o.p2;   new_p.p2];
o.p3   = [o.p3;   new_p.p3];
o.p4   = [o.p4;   new_p.p4];
o.p5   = [o.p5;   new_p.p5];
o.p6   = [o.p6;   new_p.p6];
o.p7   = [o.p7;   new_p.p7];
o.p11  = [o.p11;  new_p.p11];
o.lb   = [o.lb;   new_p.lb];
o.ub   = [o.ub;   new_p.ub];
o.name = [o.name; new_p.name];

o.idbeta      = [o.idbeta;      new_p.idbeta(:)      + n];
o.idgamma     = [o.idgamma;     new_p.idgamma(:)     + n];
o.idgaussian  = [o.idgaussian;  new_p.idgaussian(:)  + n];
o.idinvgamma1 = [o.idinvgamma1; new_p.idinvgamma1(:) + n];
o.iduniform   = [o.iduniform;   new_p.iduniform(:)   + n];
o.idinvgamma2 = [o.idinvgamma2; new_p.idinvgamma2(:) + n];
o.idweibull   = [o.idweibull;   new_p.idweibull(:)   + n];

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

%@test:1
% Build a prior incrementally with add().
Prior = dprior();
try
    Prior.add('a', 'shape', 'beta',    'mean', 0.4, 'std', 0.2);
    Prior.add('b', 'shape', 'gamma',   'mean', 0.5, 'std', 0.1);
    Prior.add('c', 'shape', 'normal',  'mean', 0.0, 'std', 1.0);
    t(1) = true;
catch
    t(1) = false;
end
if t(1)
    t(2) = length(Prior) == 3;
    t(3) = isequal(Prior.name, {'a'; 'b'; 'c'});
    t(4) = isequal(Prior.idbeta, 1);
    t(5) = isequal(Prior.idgamma, 2);
    t(6) = isequal(Prior.idgaussian, 3);
    x = Prior.draw();
    t(7) = length(x) == 3;
end
T = all(t);
%@eof:1

%@test:2
% add() returns the same handle; chaining leaves the original mutated.
Prior = dprior();
try
    Q = Prior.add('x', 'shape', 'normal', 'mean', 0.0, 'std', 1.0);
    t(1) = true;
catch
    t(1) = false;
end
if t(1)
    t(2) = Q == Prior;                   % same handle
    t(3) = length(Prior) == 1;           % original was mutated
    t(4) = isequal(Prior.name, {'x'});
end
T = all(t);
%@eof:2
