#ifndef __cmt_fragment_h__
#define __cmt_fragment_h__

#include <stdarg.h>

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

class Variable
{
public:

  typedef cmt_vector<Variable> VariableVector;

  static Variable* find (VariableVector& vector, 
                         const cmt_string& name);

public:

  Variable ();
  Variable (const cmt_string& n);

  const cmt_string& macro_braces () const;
  const cmt_string& macro_pars () const;

  void set (const cmt_string& new_name,
            const cmt_string& new_value = "");

  Variable& operator = (const Variable& other);
  Variable& operator = (const cmt_string& v);
  void operator += (const cmt_string& v);
  cmt_string operator + (const cmt_string& v) const;
  operator const cmt_string& () const;
  bool operator == (const cmt_string& v) const;
  bool operator != (const cmt_string& v) const;
  cmt_string name;
  cmt_string value;

private:
  cmt_string m_macro_braces;
  cmt_string m_macro_pars;
};

class Fragment
{
public:
  typedef cmt_vector<Fragment> FragmentVector;

  static void action (const CmtSystem::cmt_string_vector& words,
                      Use* use);
  static Fragment* find (const cmt_string& name);
  static void add (const cmt_string& name,
                   const cmt_string& suffix,
                   const cmt_string& header,
                   const cmt_string& trailer,
                   bool need_dependencies,
                   Use* use);
  static void show (const cmt_string& name);
  static void show_all ();
  static void clear_all ();
  static bool copy (FILE* out, const cmt_string& name, int variables, ...);
  static bool copy (cmt_string& out, const cmt_string& name, int variables, ...);
  static bool copy (FILE* out, const cmt_string& name, 
                    const Variable::VariableVector& vector, int variables, ...);
  static bool copy (cmt_string& out, const cmt_string& name, 
                    const Variable::VariableVector& vector, int variables, ...);

  static FragmentVector& fragments ();

public:
  Fragment ();
  Fragment (const cmt_string& fragment_name);
  ~Fragment ();
  void clear ();
  int print ();
  bool locate ();

  bool copy (FILE* out, int variables, ...);
  bool copy (cmt_string& out, int variables, ...);
  bool copy (FILE* out, int variables, va_list ids);
  bool copy (cmt_string& out, int variables, va_list ids);
  bool wincopy (FILE* out, int variables, va_list ids);
  bool wincopy (cmt_string& out, int variables, va_list ids);

  bool copy (FILE* out, const Variable::VariableVector& vector, int variables, ...);
  bool copy (cmt_string& out, const Variable::VariableVector& vector, int variables, ...);
  bool copy (FILE* out, const Variable::VariableVector& vector, int variables, va_list ids);
  bool copy (cmt_string& out, const Variable::VariableVector& vector, int variables, va_list ids);
  bool wincopy (FILE* out, const Variable::VariableVector& vector, int variables, va_list ids);
  bool wincopy (cmt_string& out, const Variable::VariableVector& vector, int variables, va_list ids);

  cmt_string name;
  cmt_string suffix;
  cmt_string header;
  cmt_string trailer;
  bool need_dependencies;
  cmt_string path;
  UseRef use;
};

class FragmentHandle
{
public:
  FragmentHandle ();
  FragmentHandle (const cmt_string name);

  FragmentHandle& operator = (const FragmentHandle& other);
  void reset ();
  void set (const cmt_string name);
  cmt_string& name ();
  cmt_string& suffix ();
  cmt_string& header ();
  cmt_string& trailer ();
  bool need_dependencies ();

  bool copy (FILE* out, int variables, ...);
  bool copy (cmt_string& out, int variables, ...);
  bool wincopy (FILE* out, int variables, ...);
  bool wincopy (cmt_string& out, int variables, ...);

  bool copy (FILE* out, const Variable::VariableVector& vector, int variables, ...);
  bool copy (cmt_string& out, const Variable::VariableVector& vector, int variables, ...);
  bool wincopy (FILE* out, const Variable::VariableVector& vector, int variables, ...);
  bool wincopy (cmt_string& out, const Variable::VariableVector& vector, int variables, ...);

private:
  bool setup ();

  Fragment* _fragment;
  cmt_string _name;
  bool _initialized;
};

#endif
