/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#ifndef cmCommandArgumentsHelper_h
#define cmCommandArgumentsHelper_h

#include "cmConfigure.h" // IWYU pragma: keep

#include <set>
#include <string>
#include <vector>

class cmCommandArgumentGroup;
class cmCommandArgumentsHelper;

/* cmCommandArgumentsHelper, cmCommandArgumentGroup and cmCommandArgument (i.e.
its derived classes cmCAXXX can be used to simplify the processing of
arguments to cmake commands. Maybe they can also be used to generate
documentation.

For every argument supported by a command one cmCommandArgument is created
and added to cmCommandArgumentsHelper. cmCommand has a cmCommandArgumentsHelper
as member variable so this should be used.

The order of the arguments is defined using the Follows(arg) method. It says
that this argument follows immediateley the given argument. It can be used
with multiple arguments if the argument can follow after different arguments.

Arguments can be arranged in groups using cmCommandArgumentGroup. Every
member of a group can follow any other member of the group. These groups
can also be used to define the order.

Once all arguments and groups are set up, cmCommandArgumentsHelper::Parse()
is called and afterwards the values of the arguments can be evaluated.

For an example see cmExportCommand.cxx.
*/
class cmCommandArgument
{
public:
  cmCommandArgument(cmCommandArgumentsHelper* args, const char* key,
                    cmCommandArgumentGroup* group = nullptr);
  virtual ~cmCommandArgument() = default;

  /// this argument may follow after arg. 0 means it comes first.
  void Follows(const cmCommandArgument* arg);

  /// this argument may follow after any of the arguments in the given group
  void FollowsGroup(const cmCommandArgumentGroup* group);

  /// Returns true if the argument was found in the argument list
  bool WasFound() const { return this->WasActive; }

  // The following methods are only called from
  // cmCommandArgumentsHelper::Parse(), but making this a friend would
  // give it access to everything

  /// Make the current argument the currently active argument
  void Activate();
  /// Consume the current string
  bool Consume(const std::string& arg);

  /// Return true if this argument may follow after the given argument.
  bool MayFollow(const cmCommandArgument* current) const;

  /** Returns true if the given key matches the key for this argument.
  If this argument has an empty key everything matches. */
  bool KeyMatches(const std::string& key) const;

  /// Make this argument follow all members of the own group
  void ApplyOwnGroup();

  /// Reset argument, so it's back to its initial state
  void Reset();

private:
  const char* Key;
  std::set<const cmCommandArgument*> ArgumentsBefore;
  cmCommandArgumentGroup* Group;
  bool WasActive;
  bool ArgumentsBeforeEmpty;
  unsigned int CurrentIndex;

  virtual bool DoConsume(const std::string& arg, unsigned int index) = 0;
  virtual void DoReset() = 0;
};

/** cmCAStringVector is to be used for arguments which can consist of more
than one string, e.g. the FILES argument in INSTALL(FILES f1 f2 f3 ...). */
class cmCAStringVector : public cmCommandArgument
{
public:
  cmCAStringVector(cmCommandArgumentsHelper* args, const char* key,
                   cmCommandArgumentGroup* group = nullptr);

  /// Return the vector of strings
  const std::vector<std::string>& GetVector() const { return this->Vector; }

  /** Is there a keyword which should be skipped in
  the arguments (e.g. ARGS for ADD_CUSTOM_COMMAND) ? */
  void SetIgnore(const char* ignore) { this->Ignore = ignore; }

private:
  std::vector<std::string> Vector;
  unsigned int DataStart;
  const char* Ignore;
  bool DoConsume(const std::string& arg, unsigned int index) override;
  void DoReset() override;
};

/** cmCAString is to be used for arguments which consist of one value,
e.g. the executable name in ADD_EXECUTABLE(). */
class cmCAString : public cmCommandArgument
{
public:
  cmCAString(cmCommandArgumentsHelper* args, const char* key,
             cmCommandArgumentGroup* group = nullptr);

  /// Return the string
  const std::string& GetString() const { return this->String; }
  const char* GetCString() const { return this->String.c_str(); }

private:
  std::string String;
  unsigned int DataStart;
  bool DoConsume(const std::string& arg, unsigned int index) override;
  void DoReset() override;
};

/** cmCAEnabler is to be used for options which are off by default and can be
enabled using a special argument, e.g. EXCLUDE_FROM_ALL in ADD_EXECUTABLE(). */
class cmCAEnabler : public cmCommandArgument
{
public:
  cmCAEnabler(cmCommandArgumentsHelper* args, const char* key,
              cmCommandArgumentGroup* group = nullptr);

  /// Has it been enabled ?
  bool IsEnabled() const { return this->Enabled; }

private:
  bool Enabled;
  bool DoConsume(const std::string& arg, unsigned int index) override;
  void DoReset() override;
};

/** cmCADisable is to be used for options which are on by default and can be
disabled using a special argument.*/
class cmCADisabler : public cmCommandArgument
{
public:
  cmCADisabler(cmCommandArgumentsHelper* args, const char* key,
               cmCommandArgumentGroup* group = nullptr);

  /// Is it still enabled ?
  bool IsEnabled() const { return this->Enabled; }

private:
  bool Enabled;
  bool DoConsume(const std::string& arg, unsigned int index) override;
  void DoReset() override;
};

/** Group of arguments, needed for ordering. E.g. WIN32, EXCLUDE_FROM_ALL and
MACSOX_BUNDLE from ADD_EXECUTABLE() are a group.
*/
class cmCommandArgumentGroup
{
  friend class cmCommandArgument;

public:
  /// All members of this group may follow the given argument
  void Follows(const cmCommandArgument* arg);

  /// All members of this group may follow all members of the given group
  void FollowsGroup(const cmCommandArgumentGroup* group);

private:
  std::vector<cmCommandArgument*> ContainedArguments;
};

class cmCommandArgumentsHelper
{
public:
  /// Parse the argument list
  void Parse(const std::vector<std::string>* args,
             std::vector<std::string>* unconsumedArgs);
  /// Add an argument.
  void AddArgument(cmCommandArgument* arg);

private:
  std::vector<cmCommandArgument*> Arguments;
};

#endif
