function [zout, zss] = epilogue_shock_decomposition(zout, x, M_, oo_)
%function [zout, zss] = epilogue_shock_decomposition(zout, x, M_, oo_)
%
% Computes the shock decomposition of the epilogue variables.
%
% INPUTS
% - zout           [3D array]   shock decomposition of endogenous variables
%                               Dimension: endo_nbr × number of decomposition components × periods
% - x              [3D array]   shock decomposition of exogenous variables
%                               Dimension: exo_nbr × number of decomposition components × periods
% - M_             [structure]  model information
% - oo_            [structure]  results
%
% OUTPUTS
% - zout           [3D array]   shock decomposition of endogenous and epilogue variables
%                               Dimension: (endo_nbr+epilogue_nbr) × number of decomposition components × periods
% - zss            [vector]     steady state of endogenous and epilogue variables.

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

ivar = varlist_indices(M_.epilogue_var_list_,M_.endo_names);
xvar = varlist_indices(M_.epilogue_varexo_list_,M_.exo_names);
y = NaN(M_.epilogue_nbr, size(zout, 2), size(zout, 3));
z=zout(ivar,:,:);
if isfield(oo_.dr,'ys')
    zss = oo_.dr.ys;
else
    zss = oo_.steady_state;
end
xss = oo_.exo_steady_state;

h_dynamic = str2func([M_.fname '.epilogue_dynamic']);
h_static = str2func([M_.fname '.epilogue_static']);

yss = h_static(zss, xss, M_.params);

for k=1:size(z,2)
    if length(ivar)>1
        ztmp = squeeze(z(:,k,:))'+zss(ivar)';
    else
        ztmp = squeeze(z(:,k,:))+zss(ivar)';
    end
    if isempty(xvar)
        xtmp = [];
    elseif length(xvar)>1
        xtmp = squeeze(x(xvar,k,:))'+xss(xvar)';
    else
        xtmp = squeeze(x(xvar,k,:))+xss(xvar)';
    end
    ds = dseries([ztmp xtmp], '', [M_.epilogue_var_list_; M_.epilogue_varexo_list_]);
    tmp = extract(h_dynamic(M_.params, ds, zss, yss), M_.epilogue_names{:});
    y(:,k,:) = tmp.data';
    y(:,k,:) = y(:,k,:) - repmat(yss, [1, 1, size(y, 3)]);
end

nterms = size(z,2);
for k=1:size(y,1)
    ytmp  = squeeze(y(k,:,:));
    yres = ytmp(end,:) - sum(ytmp(1:end-1,:));
    w = abs(ytmp(1:end-1,:))./sum(abs(ytmp(1:end-1,:)));
    %     ytmp(1:end-1,:) = ytmp(1:end-1,:) + repmat(yres,[nterms-1 1])/(nterms-1);
    ytmp(1:end-1,:) = ytmp(1:end-1,:) + repmat(yres,[nterms-1 1]).*w;
    y(k,:,:) = ytmp;
end

zout = cat(1,zout,y);
zss = [zss; yss];
