#ifndef __cmt_pattern_h__
#define __cmt_pattern_h__

#include "cmt_parser.h"
#include "cmt_system.h"

class Use;

class Template
{
public:
	typedef cmt_vector<Template> TemplateVector;
	cmt_string name;
	cmt_string value;
};

class Pattern
{
public:
  typedef cmt_vector<Pattern> PatternVector;

  static void action (const CmtSystem::cmt_string_vector& words, Use* use);

  static Pattern* find (const cmt_string& name);
  static Pattern* find (const cmt_string& name, Use* use);
  static void add (const cmt_string& name,
                   const CmtSystem::cmt_string_vector& words,
                   int start_index,
                   bool global,
                   Use* use);

  static int pattern_number ();
  static Pattern& pattern (int index);
  static void clear_all ();
  static PatternVector& patterns ();

  static void apply_all_globals ();
  static void apply_all_globals (Use* use);
  static void show_all_names ();
  static void show_all ();
  static void show_all_applied_patterns ();
  static void show (const cmt_string& name);

public:
  Pattern ();
  ~Pattern ();

  void clear ();
  void apply () const;
  void apply (Use* constext_use) const;
  void apply (Use* constext_use,
              const Template::TemplateVector& templates) const;
  void expand (Use* constext_use,
               const Template::TemplateVector& templates,
               cmt_string& line) const;

  cmt_string name;
  CmtSystem::cmt_string_vector words;
  bool global;
  Use* use;
};

class ApplyPattern
{
public:
  typedef cmt_vector<ApplyPattern> ApplyPatternVector;

  static void action (const CmtSystem::cmt_string_vector& words,
                      Use* use);

  static ApplyPattern* add (const cmt_string& name, Use* use);

public:
  ApplyPattern ();
  ~ApplyPattern ();

  void show () const;
  void apply_globals () const;
  void apply () const;

  cmt_string name;
  Use* use;
  cmt_vector<Template> replacements;
};

class IgnorePattern
{
public:
  typedef cmt_vector<IgnorePattern> IgnorePatternVector;

  static void action (const CmtSystem::cmt_string_vector& words, Use* use);

  static IgnorePattern* find (const cmt_string& name, Use* use);
  static void add (const cmt_string& name, Use* use);

public:
  IgnorePattern ();
  ~IgnorePattern ();

  void show () const;

  cmt_string name;
  Use* use;
};

#endif
