// Copyright (C) 2022 Olaf Till <i7tiol@t-online.de>
//
// This program 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.
//
// This program 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
// this program; if not, see <http://www.gnu.org/licenses/>.

#include <octave/oct.h>
// needed for older Octave versions, as 4.4
#include <octave/ov-fcn-handle.h>

#include "config.h"

DEFUN_DLD (__max_nargin_optim__, args, ,
  "-*- texinfo -*-\n\
@deftypefn {Loadable Function} {@var{n} =} ____ (@var{fh})\n\
Undocumented internal function.\n\
@end deftypefn")
{
  std::string fname ("__max_nargin_optim__");

  octave_value retval;

  if (args.length () != 1)
    {
      print_usage ();

      return retval;
    }

  octave_value fh = args(0);

  if (! fh.is_function_handle ()) {

    error ("%s: argument not a function handle", fname.c_str ());

    return retval;
  }

  octave_fcn_handle *hdl = fh.fcn_handle_value ();

  std::string name = hdl->fcn_name ();

  octave_value fcn = hdl->fcn_val ();

  if (! fcn.is_defined ()) {

    // Functions defined in a script or on the commandline need this.
    fcn = OCTAVE__INTERPRETER__SYMBOL_TABLE__FIND_FUNCTION (name);

    if (! fcn.is_defined ()) {

      error ("%s: function '%s' not found", fname.c_str (), name.c_str ());

      return retval;
    }
  }

  if (fcn.user_function_value ()->parameter_list ()->takes_varargs ()) {

    retval = octave_value (std::numeric_limits<double>::infinity ());
  }
  else {

    // Contrary to ->length (), ->size () should work both with older
    // octave versions which derive 'tree_parameter_list' from
    // 'base_list' and with newer octave versions which derive
    // 'tree_parameter_list' from 'std::list'.
    retval = octave_value
      (fcn.user_function_value ()->parameter_list ()->size ());
  }

  return retval;
}
