function smoother_info = set_smoother_info(M_, dr, options_, var_list_)

% Builds the smoother_info struct carrying the four index vectors used by
% the Kalman smoother pipeline.
%
% INPUTS
% - M_         [struct]   model description
% - dr         [struct]   decision rule (with inv_order_var, order_var)
% - options_   [struct]   options (uses varobs_id, selected_variables_only,
%                          forecast, mh_replic, load_mh_file)
% - var_list_  [cell]     list of variables to include; defaults to all
%                         endogenous names
%
% OUTPUTS
% - smoother_info          [struct]   with fields
%     .var_list            positions of observed + requested smoothed vars in dr order
%     .saved_var_list      positions of requested smoothed vars within .var_list
%     .restrict_columns    positions of states within .var_list
%     .mf                  positions of observed vars within .var_list

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

if nargin < 4 || isempty(var_list_)
    var_list_ = M_.endo_names;
end

k1 = options_.varobs_id';
if ~isempty(M_.filter_tunes)
    filter_tunes_endo_id = unique([M_.filter_tunes.endo_id]);
    k1 = [k1; filter_tunes_endo_id'];
end
var_obs_index_dr = dr.inv_order_var(k1)';

k3 = [];
if options_.selected_variables_only
    if options_.forecast > 0 && options_.mh_replic == 0 && ~options_.load_mh_file
        k3 = (1:M_.endo_nbr)';
    else
        for i=1:length(var_list_)
            k3 = [k3; strmatch(var_list_{i}, M_.endo_names(dr.order_var), 'exact')];
        end
    end
else
    k3 = (1:M_.endo_nbr)';
end

k2 = union(var_obs_index_dr, (M_.nstatic+1:M_.nstatic+M_.nspred)', 'rows');

smoother_info.var_list = union(k2, k3);
[~,~,smoother_info.saved_var_list] = intersect(k3, smoother_info.var_list(:));
[~,ic] = intersect(smoother_info.var_list, M_.nstatic+(1:M_.nspred)');
smoother_info.restrict_columns = ic;
[~,smoother_info.mf] = ismember(var_obs_index_dr, smoother_info.var_list);
