#ifndef CORE_TYPES_HPP
#define CORE_TYPES_HPP

// Détection du système cible...
#include "usgeDetectSystem.h"

namespace USpeedGameEngine
{

class USGE_Float3
{
    public:
        float x;    //!< Coordonnée ou rotation x
        float y;    //!< Coordonnée ou rotation y
        float z;    //!< Coordonnée ou rotation z

        /**
         * Constructeur par défaut.
         * @author U.Speed
         */
        inline USGE_Float3()
        {
            this->x = 0.0f;
            this->y = 0.0f;
            this->z = 0.0f;
        };
        /**
         * Constructeur.
         * @author U.Speed
         * @param xValue float : valeur de x
         * @param yValue float : valeur de y
         * @param zValue float : valeur de z
         */
        inline USGE_Float3(float xValue, float yValue, float zValue)
        {
            this->set(xValue, yValue, zValue);
        };
        /**
         * Constructeur par copie.
         * @author U.Speed
         * @param pFloat3 const USGE_Float3& : les valeurs
         */
        inline USGE_Float3(const USGE_Float3 &pFloat3)
        {
            this->set(pFloat3);
        };
        /**
         * Copie d'un objet.
         * @author U.Speed
         * @param pFloat3 const USGE_Float3& : les valeurs
         */
        inline void set(const USGE_Float3 &pFloat3)
        {
            this->x = pFloat3.x;
            this->y = pFloat3.y;
            this->z = pFloat3.z;
        };
        /**
         * Affectation de x, y et z.
         * @author U.Speed
         * @param xValue float : valeur de x
         * @param yValue float : valeur de y
         * @param zValue float : valeur de z
         */
        inline void set(float xValue, float yValue, float zValue)
        {
            this->x = xValue;
            this->y = yValue;
            this->z = zValue;
        };
        /**
         * Addition de deux triplets de "float".
         * @author U.Speed
         * @param pFloat3 const USGE_Float3& : les valeurs
         * @return USGE_Float3& : le résultat de l'addition
         */
        inline USGE_Float3 operator+(const USGE_Float3 &pFloat3) const
        {
            return USGE_Float3(this->x + pFloat3.x, this->y + pFloat3.y, this->z + pFloat3.z);
        };
        /**
         * Addition de deux triplets de "float".
         * @author U.Speed
         * @param aFloat const float : le "float" pour toutes les valeurs
         * @return USGE_Float3& : le résultat de l'addition
         */
        inline USGE_Float3 operator+(const float aFloat) const
        {
            return USGE_Float3(this->x + aFloat, this->y + aFloat, this->z + aFloat);
        };
        /**
         * Soustraction de deux triplets de "float".
         * @author U.Speed
         * @param pFloat3 const USGE_Float3& : les valeurs
         * @return USGE_Float3& : le résultat de la soustraction
         */
        inline USGE_Float3 operator-(const USGE_Float3 &pFloat3) const
        {
            return USGE_Float3(this->x - pFloat3.x, this->y - pFloat3.y, this->z - pFloat3.z);
        };
        /**
         * Soustraction de deux triplets de "float".
         * @author U.Speed
         * @param aFloat const float : le "float" pour toutes les valeurs
         * @return USGE_Float3& : le résultat de la soustraction
         */
        inline USGE_Float3 operator-(const float aFloat) const
        {
            return USGE_Float3(this->x - aFloat, this->y - aFloat, this->z - aFloat);
        };
        /**
         * Multiplication de deux triplets de "float".
         * @author U.Speed
         * @param pFloat3 const USGE_Float3& : les valeurs
         * @return USGE_Float3& : le résultat de la multiplication
         */
        inline USGE_Float3 operator*(const USGE_Float3 &pFloat3) const
        {
            return USGE_Float3(this->x * pFloat3.x, this->y * pFloat3.y, this->z * pFloat3.z);
        };
        /**
         * Multiplication de deux triplets de "float".
         * @author U.Speed
         * @param aFloat const float : le "float" pour toutes les valeurs
         * @return USGE_Float3& : le résultat de la multiplication
         */
        inline USGE_Float3 operator*(const float aFloat) const
        {
            return USGE_Float3(this->x * aFloat, this->y * aFloat, this->z * aFloat);
        };
        /**
         * Affectation des données (celui fourni sur le courant).
         * @author U.Speed
         * @param pFloat3 const USGE_Float3& : les valeurs
         * @return USGE_Float3& : le résultat de l'affectation
         */
        inline USGE_Float3 &operator=(const USGE_Float3 &pFloat3)
        {
            this->set(pFloat3);
            return(*this);
        };
        /**
         * Affectation des données (celui fourni sur le courant).
         * @author U.Speed
         * @param aFloat const float : le "float" pour toutes les valeurs
         * @return USGE_Float3& : le résultat de l'affectation
         */
        inline USGE_Float3 &operator=(const float aFloat)
        {
            this->set(aFloat, aFloat, aFloat);
            return(*this);
        };
        /**
         * Affectation des données (celui fourni sur le courant) après addition.
         * @author U.Speed
         * @param pFloat3 const USGE_Float3& : les valeurs
         * @return USGE_Float3& : le résultat de l'affectation
         */
        inline USGE_Float3 &operator+=(const USGE_Float3 &pFloat3)
        {
            (*this) = (*this) + pFloat3;
            return(*this);
        };
        /**
         * Affectation des données (celui fourni sur le courant) après addition.
         * @author U.Speed
         * @param aFloat const float : le "float" pour toutes les valeurs
         * @return USGE_Float3& : le résultat de l'affectation
         */
        inline USGE_Float3 &operator+=(const float aFloat)
        {
            (*this) = (*this) + aFloat;
            return(*this);
        };
        /**
         * Affectation des données (celui fourni sur le courant) après soustraction.
         * @author U.Speed
         * @param pFloat3 const USGE_Float3& : les valeurs
         * @return USGE_Float3& : le résultat de l'affectation
         */
        inline USGE_Float3 &operator-=(const USGE_Float3 &pFloat3)
        {
            (*this) = (*this) - pFloat3;
            return(*this);
        };
        /**
         * Affectation des données (celui fourni sur le courant) après soustraction.
         * @author U.Speed
         * @param aFloat const float : le "float" pour toutes les valeurs
         * @return USGE_Float3& : le résultat de l'affectation
         */
        inline USGE_Float3 &operator-=(const float aFloat)
        {
            (*this) = (*this) - aFloat;
            return(*this);
        };
        /**
         * Affectation des données (celui fourni sur le courant) après multiplication.
         * @author U.Speed
         * @param pFloat3 const USGE_Float3& : les valeurs
         * @return USGE_Float3& : le résultat de l'affectation
         */
        inline USGE_Float3 &operator*=(const USGE_Float3 &pFloat3)
        {
            (*this) = (*this) * pFloat3;
            return(*this);
        };
        /**
         * Affectation des données (celui fourni sur le courant) après multiplication.
         * @author U.Speed
         * @param aFloat const float : le "float" pour toutes les valeurs
         * @return USGE_Float3& : le résultat de l'affectation
         */
        inline USGE_Float3 &operator*=(const float aFloat)
        {
            (*this) = (*this) * aFloat;
            return(*this);
        };
};

/**
 * Enumération des modes disponible pour le traçage des Vertex.
 */
typedef enum EnumUSpeedGameEngineVertexMode
{
    TRIANGLES,                  //!< Traçage de triangles
    TRIANGLE_STRIP              //!< Traçage de carrés (4 points pour deux triangles)
} USGE_VertexMode;

/**
 * Enumération des modes disponibles pour les textures.
 */
typedef enum EnumUSpeedGameEngineTextureMode
{
    NEAREST,    //!< Approximatif (rapide)
    LINEAR,     //!< Linéaire (meilleur rendu que NEAREST, mais plus gourmand !)
    MIPMAP      //!< Mipmap (sur PSP : remplacé par LINEAR)
} USGE_TextureMode;

/**
 * Enumération des formats disponibles pour les textures.
 */
typedef enum EnumUSpeedGameEngineTextureFormat
{
    GREY,
    COLOR_6666,
    RGB,
    RGBA,
    
} USGE_TextureFormat;

/**
 * Structure de données pour les Vertex (points 3D).
 */
typedef struct StructUSpeedGameEngineVertex
{
    float u;            //!< Coordonnée U (= S) de mapping des textures
    float v;            //!< Coordonnée V (= T) de mapping des textures

    float nx;           //!< Coordonnée X du vecteur normal au Vertex
    float ny;           //!< Coordonnée Y du vecteur normal au Vertex
    float nz;           //!< Coordonnée Z du vecteur normal au Vertex

    float x;            //!< Coordonnée X du Vertex
    float y;            //!< Coordonnée Y du Vertex
    float z;            //!< Coordonnée Z du Vertex
} USGE_Vertex;

/**
 * Enumération des entrées disponibles.
 */
typedef enum EnumUSpeedGameEngineInputControl
{
    // POV : Point Of View
    povUP,              //!< Flèche haute
    povDOWN,            //!< Flèche basse
    povLEFT,            //!< Flèche gauche
    povRIGHT,           //!< Flèche droite
    // Les axes (6 maximum)
    axisX,              //!< L'axe X
    axisY,              //!< L'axe Y
    axisZ,              //!< L'axe Z
    axisR,              //!< L'axe R
    axisU,              //!< L'axe U
    axisV,              //!< L'axe V
    // Les boutons de la souris
    mouseLeftClick,     //!< Bouton gauche de la souris
    mouseRightClick,    //!< Bouton droit de la souris
    mouseMiddleClick,   //!< Bouton central de la souris
} USGE_InputControl;

/**
 * Énumération des types d'images pris en charge.
 */
typedef enum USpeedGameEngineEnumImageType
{
    PNG,                //!< Format PNG : Portable Network Graphics
    JPG,                //!< Format JPEG
    TGA                 //!< Format TARGA
} USGE_Image;


/**
 * Énumération des moteurs de rendus.
 * Si le moteur spécifié n'est pas pris en charge par la plateforme, c'est la version "DEFAULT".
 */
typedef enum USpeedGameEngineEnumRenderEngine
{
    DEFAULT,        //!< Le moteur de rendu par défaut.
    OPENGL,         //!< Rendu OpenGL
    DIRECTX,        //!< Rendu Direct X
    SOFTWARE        //!< Rendu logiciel
} USGE_RenderEngine;

class USGE_KeyFrame
{
    public:
        unsigned long int duration; //!< Temps de l'animation pour arriver à la cible en millisecondes
        USGE_Float3 position;       //!< Position cible
        USGE_Float3 rotation;       //!< Rotation cible

        /**
         * Constructeur par défaut.
         * @author U.Speed
         */
        inline USGE_KeyFrame()
        {
            this->clear();
        };
        /**
         * Remise à zéro de la classe.
         * @author U.Speed
         */
        inline void clear()
        {
            // Durée
            this->duration = 0;

            // Informations
            this->position = 0.0f;
            this->rotation = 0.0f;
        };
        /**
         * Affectation des données (celui fourni sur le courant).
         * @author U.Speed
         * @param pFrame const USGE_Float3& : les valeurs
         * @return USGE_Float3& : le résultat de l'affectation
         */
        inline USGE_KeyFrame &operator=(const USGE_KeyFrame &pFrame)
        {
            this->duration = pFrame.duration;
            this->position = pFrame.position;
            this->rotation = pFrame.rotation;
            return(*this);
        };
};

}        // Fin "namespace USpeedGameEngine"

#endif
