#ifndef __cmt_use_h__
#define __cmt_use_h__

#include "cmt_include.h"
#include "cmt_script.h"
#include "cmt_pattern.h"

class Use
{
public:
  typedef cmt_vector<Use> UseVector;
  typedef cmt_vector<Use*> UsePtrVector;

  static Use* action (const CmtSystem::cmt_string_vector& words, Use* use);
  static Use* find (const cmt_string& package,
                    const cmt_string& version = "",
                    const cmt_string& path = "");
  static void move (Use* use1);
  static void reorder (Use* use1, Use* use2);
  static Use* create (const cmt_string& path,
                      const cmt_string& package,
                      const cmt_string& version);
  static Use* add (const cmt_string& path,
                   const cmt_string& package,
                   const cmt_string& version,
                   Use* context_use);
  static void select_clients (const cmt_string& package,
                              const cmt_string& version);
  static void show_all (bool skip_discarded = false);
  static void show_all (const cmt_string& prefix, bool skip_discarded = false);
  static Use& current ();
  static const Use& const_current ();
  static UseVector& all_uses ();
  static UsePtrVector& uses ();
  static void clear_all ();
  static void unselect_all ();
  static void undiscard_all ();
  static void fill_macro_all (cmt_string& buffer, const cmt_string& suffix);

public:
  Use ();
  Use (const cmt_string& new_package,
       const cmt_string& new_version,
       const cmt_string& new_path);
  ~Use ();
  void clear ();
  void set (const cmt_string& new_package,
            const cmt_string& new_version,
            const cmt_string& new_path);
  void author_action (const CmtSystem::cmt_string_vector& words);
  void manager_action (const CmtSystem::cmt_string_vector& words);
  void change_path (const cmt_string& path);
  int reach_package (const cmt_string& current_path);
  bool move_to ();
  void discard ();
  void undiscard ();
  void select ();
  void unselect ();
  bool is_selected ();
  bool is_client (const cmt_string& package,
                  const cmt_string& version);
  void show_sub_uses (bool skip_discarded = false);
  bool select_alternate ();
  void apply_global_patterns ();
  void set_include_path (const cmt_string& new_path);

  void fill_includes_macro (cmt_string& buffer) const;
  void fill_macro (cmt_string& buffer, const cmt_string& suffix) const;

  Use* get_selected_version ();
  bool get_paths (Use* to, UsePtrVector& list);

  cmt_string package;            /* directly read from requirements */
  cmt_string specified_version;  /* idem                            */
  cmt_string specified_path;     /* idem                            */
  cmt_string author;             /* idem                            */
  cmt_string manager;            /* idem                            */

  cmt_string path;               /* expanded path                   */
  cmt_string version;            /* idem                            */
  cmt_string real_path;
  CmtDirStyle style;             /* May be cmt or mgr               */

  cmt_string prefix;             /* upper case copy of package      */
  ScopeType scope;               /* copy of the current scope       */
  bool done;                     /* true when requirements file has
                                    already been read               */
  bool discarded;                /* discarded by version strategy   */
  bool selected;                 /* used for recursive access       */

  bool auto_imports;

  Include::IncludeVector includes;
  cmt_string include_path;
  Script::ScriptVector scripts;
  ApplyPattern::ApplyPatternVector apply_patterns;
  IgnorePattern::IgnorePatternVector ignore_patterns;

private:
  static bool need_new (const cmt_string& path,
                        const cmt_string& package,
                        const cmt_string& version,
                        Use** old_use);

  UsePtrVector sub_uses;
  CmtSystem::cmt_string_vector alternate_versions;
  CmtSystem::cmt_string_vector alternate_paths;
};

#endif
