#ifndef __VARIANT_H
#define __VARIANT_H

#ifndef __DATE_H
#include <date.h>
#endif

#ifndef __REAL_H
#include <real.h>
#endif

#ifndef __RECTYPES_H
#include <rectypes.h>
#endif

///////////////////////////////////////////////////////////
// TVariant
///////////////////////////////////////////////////////////

class TVariant : public TSortable
{
  TFieldtypes _type;
  void* _ptr;

protected:
  virtual TObject* dup() const { return new TVariant(*this); }
  virtual word class_id() const { return CLASS_VARIANT; }
  virtual bool is_kind_of(word cid) const;
  void copy(const TVariant& var);

public:
  TFieldtypes type() const { return _type; } // Internal use only
  bool is_string() const { return _type == _alfafld; }
  bool is_date() const { return _type == _datefld; }
  bool is_real() const { return _type == _realfld; }
  bool is_empty() const;
  bool is_null() const { return _type == _nullfld; }
  bool is_zero() const;
  void set_null();
  
  void set(const char* str);
  void set(const real& r);
  void set(const long n);
  void set(const TDate& d);

  TVariant& operator=(const TVariant& var) { copy(var); return *this; }
  TVariant& operator=(const char* str) { set(str); return *this; }
  TVariant& operator=(const real& r) { set(r); return *this; }
  TVariant& operator=(const long n) { set(n); return *this; }
  TVariant& operator=(const TDate& d) { set(d); return *this; }
  TVariant& operator=(bool b) { set(long(b)); return *this; }
  TVariant& operator+=(const TVariant& var) { return add(var); }

  const TString& as_string() const;
  bool as_string(TString& str) const;
  real as_real() const;
  long as_int() const;
  TDate as_date() const;
  bool as_bool() const;
  unsigned long as_color() const;

  void convert_to(TFieldtypes ft);

  virtual void print_on(ostream& out) const;
  virtual int compare(const TSortable& s) const;
  TVariant& add(const TVariant& var);
  TVariant& sub(const TVariant& var);

  TVariant() : _type(_nullfld), _ptr(NULL) { }
  TVariant(const char* str) : _type(_alfafld), _ptr(new TString(str)) { }
  TVariant(const real& num) : _type(_realfld), _ptr(new real(num)) { };
  TVariant(const TDate& d) : _type(_datefld), _ptr((void*)d.date2ansi()) { };
  TVariant(long num) : _type(_longfld), _ptr((void*)num) { };
  TVariant(bool ok) : _type(_longfld), _ptr((void*)ok) { };
  TVariant(const TVariant& var) : _type(_nullfld), _ptr(NULL) { copy(var); }
  virtual ~TVariant() { set_null(); }
};

extern const TVariant NULL_VARIANT;

class TVariant_stack : public TObject
{
  TArray _var;
  int _sp;

public:
  int items() const { return _sp; }
  bool empty() const { return _sp <= 0; }
  bool drop();
  TVariant& pop();
  TVariant& peek(int depth = 0);
  void roll(int depth);

  void push(const TVariant& var);
  void push(long n);
  void push(const real& n);
  void push(const char* str);
  void reset();
  bool overflow() const;

  TVariant_stack() : _sp(0) { }
};


#endif