/// This file is part of the X3DToolKit library
/// Copyright (C) 2002-2004  Yannick Le Goc (legoc@imag.fr)

/// http://artis.imag.fr/Members/Yannick.Legoc/X3D/

/// This library is free software; you can redistribute it and/or
/// modify it under the terms of the GNU Lesser General Public
/// License as published by the Free Software Foundation; either
/// version 2.1 of the License, or (at your option) any later version.

/// This library is distributed in the hope that it will be useful,
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
/// Lesser General Public License for more details.

/// You should have received a copy of the GNU Lesser General Public
/// License along with this library; if not, write to the Free Software
/// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#ifndef X3DTK_X3DBASETYPES_H
#define X3DTK_X3DBASETYPES_H

#include "Platform.h"
#include "SFString.h"
#include "SFVec3f.h"
#include "SFVec2f.h"
#include "SFPoint3f.h"
#include "SFPoint2f.h"
#include "SFMatrix34f.h"

#include <iostream>
#include <string>
#include <list>
#include <vector>
#include <map>

/// namespace including all the classes of the X3DToolKit library. 

namespace X3DTK {

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing an empty type called
 * nil.
 *
 *  \ingroup base
 */

class nil {};

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple SFString values
 *  deriving from std::vector<SFString>.
 *
 *  \ingroup base
 */

class MFString : public std::vector<SFString>
{
public:
  /// Constructor.
  MFString() {};
  /// Constructor from a SFString.
  explicit MFString(const SFString &s);
  /// Converts into string.  
  SFString toSFString() const;
};

/*! \brief Type declared in <b><X3DTK/kernel.h></b> providing a boolean.
 *
 *  \ingroup base
 */

typedef bool SFBool;

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple SFBool values
 *  deriving from std::vector<SFBool>.
 *
 *  \ingroup base
 */

class MFBool : public std::vector<SFBool>
{
public:
  /// Constructor.
  MFBool(){};
  /// Constructor from a SFString.
  explicit MFBool(const SFString &s);
  /// Converts into string.  
  SFString toSFString() const;
};

/*! \brief Type declared in <b><X3DTK/kernel.h></b> providing an integer.
 *
 *  \ingroup base
 */

typedef int SFInt32;

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple SFInt32 values
 *  deriving from std::vector<SFInt32>.
 *
 *  \ingroup base
 */

class MFInt32 : public std::vector<SFInt32>
{
public:
  /// Constructor.
  MFInt32(){};
  /// Constructs a MFInt32 of size n.
  explicit MFInt32(size_type n, const SFInt32 &V = SFInt32()); 
  /// Constructor from a SFString.
  explicit MFInt32(const SFString &s);
  /// Converts into string.  
  SFString toSFString() const;
};

/*! \brief Type declared in <b><X3DTK/kernel.h></b> providing a float.
 *
 *  \ingroup base
 */

typedef float SFFloat;

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple SFFloat values
 *  deriving from std::vector<SFFloat>.
 *
 *  \ingroup base
 */

class MFFloat : public std::vector<SFFloat>
{
public:
  /// Constructor.
  MFFloat(){};
  /// Constructs a MFFloat of size n.
  explicit MFFloat(size_type n, const SFFloat &V = SFFloat());
  /// Constructor from a SFString.
  explicit MFFloat(const SFString &s);
  /// Converts into string.  
  SFString toSFString() const;
};

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a double.
 *
 *  \ingroup base
 */

typedef double SFDouble;

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple SFDouble values
 *  deriving from std::vector<SFDouble>.
 *
 *  \ingroup base
 */

class MFDouble : public std::vector<SFDouble>
{
public:
  /// Constructor.
  MFDouble(){};
  /// Constructor from a SFString.
  explicit MFDouble(const SFString &s);
  /// Converts into string.  
  SFString toSFString() const;
};

class SFColor;

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing an SFColorRGBA.
 *
 *  \ingroup base
 */

class SFColorRGBA
{
public:
  /// Red canal.
  SFFloat r;
  /// Green canal.
  SFFloat g;
  /// Blue canal.
  SFFloat b;
  /// Alpha canal.
  SFFloat a;
  /// Constructor.  
  SFColorRGBA(){};
  /// Constructor from SFColor.  
  SFColorRGBA(const SFColor &color);
  /// Constructor from the attributes.  
  SFColorRGBA(SFFloat r, SFFloat g, SFFloat b, SFFloat a);
  /// Constructor from a SFString.
  explicit SFColorRGBA(const SFString &s);
   /// Returns the pointed array.
  inline float *f_data() {return &r;};
  /// Returns the pointed array.
  inline const float *f_data() const {return &r;};
  /// Returns the pointed array.
  inline operator float *() {return &r;};
  /// Returns the pointed array.
  inline operator const float *() const {return &r;};
 
  /// == operator.
  friend bool operator== (const SFColorRGBA &r1, const SFColorRGBA &r2);
  /// != operator.
  friend bool operator!= (const SFColorRGBA &r1, const SFColorRGBA &r2);
  /// Converts into string.  
  SFString toSFString() const;  
  
  /// null color.
  static const SFColorRGBA null;
};

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple SFColorRGBA values
 *  deriving from std::vector<SFColorRGBA>.
 *
 *  \ingroup base
 */

class MFColorRGBA : public std::vector<SFColorRGBA>
{
public:
  /// Constructor.
  MFColorRGBA(){};
  /// Constructs a MFColorRGBA of size n.
  MFColorRGBA(size_type n, const SFColorRGBA &C = SFColorRGBA());
  /// Constructor from a SFString.
  explicit MFColorRGBA(const SFString &s);
  /// Converts into string.  
  SFString toSFString() const;
};

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing an SFColor containing
*  the red, green and blue canals.
 *
 *  \ingroup base
 */

class SFColor
{
public:
  /// Red canal.
  SFFloat r;
  /// Green canal.
  SFFloat g;
  /// Blue canal.
  SFFloat b;
  /// Constructor.
  SFColor(){};
  /// Constructor from the attributes.
  SFColor(SFFloat r, SFFloat g, SFFloat b);
  /// Constructor from a SFString.
  explicit SFColor(const SFString &s);
  /// Returns the pointed array.
  inline float *f_data() {return &r;};
  /// Returns the pointed array.
  inline const float *f_data() const {return &r;};
  /// Returns the pointed array.
  inline operator float *() {return &r;};
  /// Returns the pointed array.
  inline operator const float *() const {return &r;};
 
  /// == operator.
  friend bool operator== (const SFColor &r1, const SFColor &r2);
  /// != operator.
  friend bool operator!= (const SFColor &r1, const SFColor &r2);
  /// Converts into string.  
  SFString toSFString() const;
  
  /// null color.
  static const SFColor null;
};

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple SFColor values
 *  deriving from std::vector<SFColor>.
 *
 *  \ingroup base
 */

class MFColor : public std::vector<SFColor>
{
public:
  /// Constructor.  
  MFColor(){};
  /// Constructor from a SFString.
  explicit MFColor(const SFString &s);
  /// Conversion operator to MFColorRGBA.
  operator const MFColorRGBA() const;
  /// Converts into string.  
  SFString toSFString() const;
};

class X3DAbstractNode;

/*! \brief Type declared in <b><X3DTK/kernel.h></b> providing a pointer to X3DAbstractNode.
 *
 *  \ingroup base
 */

typedef X3DAbstractNode *SFNode;

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple pointer to X3DAbstractNode values
 *  deriving from std::list<X3DAbstractNode *>.
 *
 *  \ingroup base
 */

typedef std::list<X3DAbstractNode *> MFNode;

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a 2D vector of SFDouble.
 *
 *  \ingroup base
 */

class SFVec2d
{
public:
  SFDouble x, y;
  /// Constructor.  
  SFVec2d();
  /// Constructor from the attributes.
  SFVec2d(SFDouble x, SFDouble y);
  /// Constructor from a SFString.
  explicit SFVec2d(const SFString &s);
  /// Converts into string.  
  SFString toSFString() const;
};
  
/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple SFVec2d values
 *  deriving from std::vector<SFVec2d>.
 *
 *  \ingroup base
 */

class MFVec2d : public std::vector<SFVec2d>
{
public:
  /// Constructor.    
  MFVec2d(){};
  /// Constructor from a SFString.
  explicit MFVec2d(const SFString &s);
  /// Converts into string.  
  SFString toSFString() const;
};
  
/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple SFVec2f values
 *  deriving from std::vector<SFVec2f>.
 *
 *  \ingroup base
 */

class MFVec2f : public std::vector<SFVec2f>
{
public:
  /// Constructor.  
  MFVec2f(){};
  /// Constructs a MFVec2f of size n.
  explicit MFVec2f(size_type n, const SFVec2f &V = SFVec2f());
  /// Constructor from a SFString.
  explicit MFVec2f(const SFString &s);
  /// Converts into string.  
  SFString toSFString() const;
};

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple SFPoint2f values
 *  deriving from std::vector<SFPoint2f>.
 *
 *  \ingroup base
 */

class MFPoint2f : public std::vector<SFPoint2f>
{
public:
  /// Constructor.  
  MFPoint2f(){};
  /// Constructs a MFPoint2f of size n.
  explicit MFPoint2f(size_type n, const SFPoint2f &V = SFPoint2f());
  /// Constructor from a SFString.
  explicit MFPoint2f(const SFString &s);
  /// Converts into string.  
  SFString toSFString() const;
};

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a 3D vector of double.
 *
 *  \ingroup base
 */

class SFVec3d
{
public:
  SFDouble x, y, z;
  /// Constructor.    
  SFVec3d();
  /// Constructor from the attributes.    
  SFVec3d(SFDouble x, SFDouble y, SFDouble z);
  /// Constructor from a SFString.
  explicit SFVec3d(const SFString &s);    
  /// Converts into string.  
  SFString toSFString() const;
};

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple SFVec3d values
 *  deriving from std::vector<SFVec3d>.
 *
 *  \ingroup base
 */

class MFVec3d : public std::vector<SFVec3d>
{
public:
  /// Constructor.  
  MFVec3d(){};
  /// Constructor from a SFString.
  explicit MFVec3d(const SFString &s);
  /// Converts into string.  
  SFString toSFString() const;
};

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple SFVec3f values
 *  deriving from std::vector<SFVec3f>.
 *
 *  \ingroup base
 */

class MFVec3f : public std::vector<SFVec3f>
{
public:
  /// Constructor.  
  MFVec3f(){};
  /// Constructs a MFVec3f of size n.
  explicit MFVec3f(size_type n, const SFVec3f &V = SFVec3f());
  /// Constructor from a SFString.
  explicit MFVec3f(const SFString &s);
  /// Converts into string.  
  SFString toSFString() const;
};

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple SFPoint3f values
 *  deriving from std::vector<SFPoint3f>.
 *
 *  \ingroup base
 */

class MFPoint3f : public std::vector<SFPoint3f>
{
public:
  /// Constructor.  
  MFPoint3f(){};
  /// Constructs a MFVec3f of size n.
  explicit MFPoint3f(size_type n, const SFPoint3f &V = SFPoint3f());
  /// Constructor from a SFString.
  explicit MFPoint3f(const SFString &s);
  /// Converts into string.  
  SFString toSFString() const;
};

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a rotation defined by its
 *  orientation vector x, y, z and its angle.
 *
 *  \ingroup base
 */

class SFRotation
{
public:
  SFFloat x, y, z, angle;
  /// Constructor.  
  SFRotation(){};
  /// Constructor from the attributes.    
  SFRotation(SFFloat x, SFFloat y, SFFloat z, SFFloat angle);
  /// Constructor from a SFString.
  explicit SFRotation(const SFString &s);
  /// Converts into string.  
  SFString toSFString() const;
  
  /// == operator.    
  friend bool operator== (const SFRotation &r1, const SFRotation &r2);
  /// != operator.
  friend bool operator!= (const SFRotation &r1, const SFRotation &r2);
};


/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple SFString values
 *  deriving from std::vector<SFString>.
 *
 *  \ingroup base
 */

class MFRotation : public std::vector<SFRotation>
{
public:
  /// Constructor.
  MFRotation(){};
  /// Constructor from a SFString.
  explicit MFRotation(const SFString &s);
  /// Converts into string.  
  SFString toSFString() const;
};

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a double value for PI.
 *
 *  \ingroup base
 */

static const double PI = 3.14159265358979323846;

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a double value for 180/PI.
 *
 *  \ingroup base
 */

static const double radCoef = 180.0/PI;

/*! \brief Function declared in <b><X3DTK/kernel.h></b> providing a conversion
 *  from radians to degrees, used for GL rotations. 
 *
 *  \ingroup base
 */

inline SFFloat radiansToDegrees(SFFloat alpha)
{
  return static_cast<SFFloat>(radCoef*alpha);
}

}

#ifndef DOXYGEN

namespace X3DTK {

struct eqSFString
{
  inline bool operator()(const SFString &s1, const SFString &s2) const
  {
    return s1 == s2;
  }
};

struct ltSFString
{
  bool operator()(const SFString &s1, const SFString &s2) const
  {
    return strcmp(s1, s2) < 0;
  }
};

}

#endif

namespace X3DTK {

// other types
class SFType;
class SFComponent;
class SFSceneGraph;
class WalkFunction;
class VisitingFunctions;
class EnterFunction;
class WalkOnFunction;
class CreationFunction;
class LeaveFunction;

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple SFType values
 *  deriving from std::vector<SFType>.
 *
 *  \ingroup base
 */

typedef std::map<SFString, SFType *, ltSFString> MFType;

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple SFComponent values
 *  deriving from std::vector<SFComponent>.
 *
 *  \ingroup base
 */

typedef std::map<SFString, SFComponent *, ltSFString> MFComponent;

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple SFSceneGraph values
 *  deriving from std::vector<SFSceneGraph>.
 *
 *  \ingroup base
 */

typedef std::map<SFString, SFSceneGraph *, ltSFString> MFSceneGraph;

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a dictionary for pointer to WalkFunction. 
 *
 *  \ingroup base
 */

typedef std::map<SFString, WalkFunction *, ltSFString> WalkingDict;

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a dictionary for pointer to EnterFunction. 
 *
 *  \ingroup base
 */

typedef std::map<SFString, EnterFunction *, ltSFString> EnterDict;

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a dictionary for pointer to WalkOnFunction. 
 *
 *  \ingroup base
 */

typedef std::map<SFString, WalkOnFunction *, ltSFString> WalkOnDict;

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a dictionary for pointer to LeaveFunction. 
 *
 *  \ingroup base
 */

typedef std::map<SFString, LeaveFunction *, ltSFString> LeaveDict;

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a dictionary for pointer to CreationFunction. 
 *
 *  \ingroup base
 */

typedef std::map<SFString, CreationFunction *, ltSFString> CreationDict;


/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple pointer to WalkFunction values
 *  deriving from std::vector<WalkFunction *>.
 *
 *  \ingroup base
 */

typedef std::vector<WalkFunction *> WalkingArray;

/*! \brief Class declared in <b><X3DTK/kernel.h></b> providing a multiple pointer to VisitingFunctions values
 *  deriving from std::vector<VisitingFunctions *>.
 *
 *  \ingroup base
 */

typedef std::vector<VisitingFunctions *> VisitingArray;

/// operator<< overloaded for MFString class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const MFString &ms);
/// operator<< overloaded for MFBool class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const MFBool &mb);
/// operator<< overloaded for MFint32 class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const MFInt32 &mi);
/// operator<< overloaded for MFFloat class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const MFFloat &mf);
/// operator<< overloaded for MFDouble class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const MFDouble &md);
/// operator<< overloaded for SFColor class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const SFColor &c);
/// operator<< overloaded for MFColor class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const MFColor &mc);
/// operator<< overloaded for SFColorRGBA class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const SFColorRGBA &c);
/// operator<< overloaded for MFColorRGBA class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const MFColorRGBA &mc);
/// operator<< overloaded for SFVec2d class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const SFVec2d &v);
/// operator<< overloaded for MFVec2d class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const MFVec2d &mv);
/// operator<< overloaded for SFVec2f class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const SFVec2f &v);
/// operator<< overloaded for MFVec2f class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const MFVec2f &mv);
/// operator<< overloaded for SFVec3d class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const SFVec3d &v);
/// operator<< overloaded for MFVec3d class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const MFVec3d &mv);
/// operator<< overloaded for SFVec3f class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const SFVec3f &v);
/// operator<< overloaded for MFVec3f class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const MFVec3f &mv);
/// operator<< overloaded for SFPoint3f class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const SFPoint3f &v);
/// operator<< overloaded for SFRotation class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const SFRotation &r);
/// operator<< overloaded for MFRotation class respecting the X3D notation
std::ostream& operator<<(std::ostream& o, const MFRotation &mr);
/// Overloaded operator<< for SFMatrix34f.
std::ostream& operator<<(std::ostream& o, const SFMatrix34f &M);

}

#endif
