// This code was generated by CLI, a command line interface
// compiler for C++.
//

#ifndef COMMAND_LINE_OPTIONS_HXX
#define COMMAND_LINE_OPTIONS_HXX

#include <iosfwd>
#include <string>
#include <exception>

namespace cli
{
  class unknown_mode
  {
    public:
    enum value
    {
      skip,
      stop,
      fail
    };

    unknown_mode (value v);

    operator value () const 
    {
      return v_;
    }

    private:
    value v_;
  };

  // Exceptions.
  //

  class exception: public std::exception
  {
    public:
    virtual void
    print (std::ostream&) const = 0;
  };

  std::ostream&
  operator<< (std::ostream&, const exception&);

  class unknown_option: public exception
  {
    public:
    
    ~unknown_option () throw () override;

    unknown_option (std::string  option);

    const std::string&
    option () const;

    void
    print (std::ostream&) const override;

    const char*
    what () const throw () override;

    private:
    std::string option_;
  };

  class unknown_argument: public exception
  {
    public:
    
    ~unknown_argument () throw () override;

    unknown_argument (std::string  argument);

    const std::string&
    argument () const;

    void
    print (std::ostream&) const override;

    const char*
    what () const throw () override;

    private:
    std::string argument_;
  };

  class missing_value: public exception
  {
    public:
    
    ~missing_value () throw () override;

    missing_value (std::string  option);

    const std::string&
    option () const;

    void
    print (std::ostream&) const override;

    const char*
    what () const throw () override;

    private:
    std::string option_;
  };

  class invalid_value: public exception
  {
    public:
    
    ~invalid_value () throw () override;

    invalid_value (std::string  option,
                   std::string  value);

    const std::string&
    option () const;

    const std::string&
    value () const;

    void
    print (std::ostream&) const override;

    const char*
    what () const throw () override;

    private:
    std::string option_;
    std::string value_;
  };

  class eos_reached: public exception
  {
    public:
    void
    print (std::ostream&) const override;

    const char*
    what () const throw () override;
  };

  class scanner
  {
    public:
    virtual
    ~scanner ();

    virtual bool
    more () = 0;

    virtual const char*
    peek () = 0;

    virtual const char*
    next () = 0;

    virtual void
    skip () = 0;
  };

  class argv_scanner: public scanner
  {
    public:
    argv_scanner (int& argc, char** argv, bool erase = false);
    argv_scanner (int start, int& argc, char** argv, bool erase = false);

    int
    end () const;

    bool
    more () override;

    const char*
    peek () override;

    const char*
    next () override;

    void
    skip () override;

    private:
    int i_;
    int& argc_;
    char** argv_;
    bool erase_;
  };
}

#include <string>

class options
{
  public:

  options (int& argc,
           char** argv,
           bool erase = false,
           ::cli::unknown_mode option = ::cli::unknown_mode::fail,
           ::cli::unknown_mode argument = ::cli::unknown_mode::stop);

  options (int start,
           int& argc,
           char** argv,
           bool erase = false,
           ::cli::unknown_mode option = ::cli::unknown_mode::fail,
           ::cli::unknown_mode argument = ::cli::unknown_mode::stop);

  options (int& argc,
           char** argv,
           int& end,
           bool erase = false,
           ::cli::unknown_mode option = ::cli::unknown_mode::fail,
           ::cli::unknown_mode argument = ::cli::unknown_mode::stop);

  options (int start,
           int& argc,
           char** argv,
           int& end,
           bool erase = false,
           ::cli::unknown_mode option = ::cli::unknown_mode::fail,
           ::cli::unknown_mode argument = ::cli::unknown_mode::stop);

  options (::cli::scanner&,
           ::cli::unknown_mode option = ::cli::unknown_mode::fail,
           ::cli::unknown_mode argument = ::cli::unknown_mode::stop);

  // Option accessors.
  //

  const bool&
  help () const;

  const std::string&
  action () const;

  const std::string&
  input () const;

  const std::string&
  component () const;

  // Print usage information.
  //
  static void
  print_usage (::std::ostream&);

  private:
  void
  _parse (::cli::scanner&,
          ::cli::unknown_mode option,
          ::cli::unknown_mode argument);

  public:
  bool help_;
  std::string action_;
  std::string input_;
  std::string component_;
};

#include "CommandLineOptions.ixx"

#endif // COMMAND_LINE_OPTIONS_HXX
