#ifndef DPUSERTYPE_H
#define DPUSERTYPE_H

/*
 * Definition of class dpuserType:
 * this is a superclass which includes the following DPUSER variable types:
 *   - integer     (lvalue)
 *   - double      (dvalue)
 *   - complex     (*cvalue)   [pointer]
 *   - string      (*svalue)   [pointer]
 *   - stringarray (*arrvalue) [pointer]
 *   - fits        (*fvalue)   [pointer]
 *   - fitsfile    (*ffvalue)  [pointer]
 *
 * This class throws the dpuserTypeException if some operation can't be performed
 */

#include <vector>
#include <iostream>

typedef enum { typeUnknown = 0, typeCon = 0x01, typeId = 0x02, typeOpr = 0x04,
typeDbl = 0x08, typeFnc = 0x10, typeStr = 0x20, typeCom = 0x40,
typeFits = 0x80, typeFitsFile = 0x100, typeRng = 0x200, typePgplot = 0x400,
typeStrarr = 0x800, typeDpArr = 0x1000 } nodeEnum;

class dpString;
class dpComplex;
class dpStringList;
class Fits;
class dpuserTypeList;

class dpuserTypeException {
public:
	dpuserTypeException(char *why);
	const char *reason();
private:
    std::string cause;
};

class dpuserType {
public:
	dpuserType();
	dpuserType(const dpuserType &);
	dpuserType(const int &);
	dpuserType(const char *);
	dpuserType(const double &);
    void fromRI(const double &, const double &);
//    ~dpuserType();    // don't implement this!
                        // dpuserType often contains shallow copies of conValues etc..!!!!

    friend std::ostream& operator<< (std::ostream &out, const dpuserType &value);

	void initialize();
    void copy(const dpuserType &);
    bool deep_copy(const dpuserType &);
	void clone(const dpuserType &);
	
	double toDouble() const;
	float toFloat();
	long toInt() const;
    double toReal() const;
    double toImag() const;
	dpString toString();
    const char *c_str() const;
	bool isReal() const;
	bool isInt() const;

    nodeEnum       type;
    long           lvalue;
    double         dvalue;
    dpComplex      *cvalue;
    dpString       *svalue;
    dpStringList   *arrvalue;
    Fits           *fvalue;
    dpString       *ffvalue;
    dpuserTypeList *dparrvalue;

    bool variable;

	dpuserType &operator=(const int &i);
	dpuserType &operator=(const long &l);
	dpuserType &operator=(const double &d);
	dpuserType &operator=(const dpComplex &c);
	dpuserType &operator=(const Fits &f);
	dpuserType &operator=(const dpString &s);
	dpuserType &operator=(const dpStringList &a);
	dpuserType &operator=(const dpuserType &a);

	dpuserType operator-();

	dpuserType operator++(int);
	dpuserType &operator++();
	dpuserType operator--(int);
	dpuserType &operator--();

	dpuserType &operator +=(const dpuserType &arg);
	dpuserType &operator -=(const dpuserType &arg);
	dpuserType &operator *=(const dpuserType &arg);
	dpuserType &operator /=(const dpuserType &arg);

    bool operator<(const dpuserType arg);
	bool operator<=(const dpuserType arg);
	bool operator>(const dpuserType arg);
	bool operator>=(const dpuserType arg);
	bool operator==(const dpuserType arg);
	bool operator!=(const dpuserType arg);

    const char *getFileName(void) const;
    const char* getColumnName() const;
    bool showAsTable();
};

dpuserType ReadFITSBinTable(const char *fname, dpuserType ext, dpuserType col);

class dpuserTypeList : public std::vector<dpuserType*> {
public:
    dpuserTypeList() {}
    dpuserTypeList(const dpuserTypeList &);
    ~dpuserTypeList();

    bool ReadFITS(const dpString &);
    bool showAsTable();
};

// END PARSE FOR DPUSER2C

#endif /* DPUSERTYPE_H */
