#ifndef LD_TYPES_H
#define LD_TYPES_H


namespace LD
{
  enum TextureTypes
  {
    TEX_DUMMY,
    TEX_PLAYER_SHIP,
    TEX_CLOUD,
    TEX_GRID_FILLED,
    TEX_PLAYER_SHOT,
    TEX_PARTICLE,
    TEX_EMERALD,
    TEX_UFO_1,
    TEX_UFO_2,
    TEX_UFO_3,
    TEX_FIRE_PARTICLE,

    TEX_LAST_ENTRY
  };

  enum GameObjectType
  {
    GO_INVALID = 0,
    GO_PLAYER,
    GO_PLAYER_SHOT,
    GO_CLOUD,
    GO_EMERALD,
    GO_UFO,

    GO_LAST_ENTRY
  };

  enum SoundTypes
  {
    SOUND_SHOT,
    SOUND_PLAYER_DIED,
    SOUND_LOST_TILE,
    SOUND_WIN_TILE,
    SOUND_EXPLODE,
    SOUND_COLLECT_EMERALD,
    SOUND_SPAWN_UFO,
    SOUND_SHOT_HIT,

    SOUND_LAST_ENTRY
  };

  template <class T> class PointT
  {

  public:


    typedef T scalar_type;

    scalar_type x;
    scalar_type y;



    PointT() : x( 0 ), y( 0 ) {}
    PointT( const scalar_type& sx, const scalar_type& sy ) : x( sx ), y( sy ) {}
    PointT( const PointT& v ) : x( v.x ), y( v.y ) {}


    PointT& set( const scalar_type  s ) {
      x = y = s; return *this;
    }
    PointT& set( const scalar_type& sx, const scalar_type& sy ) {
      x = sx; y = sy; return *this;
    }
    PointT& clear() {
      x = y = 0; return *this;
    }
    //- assignment
    PointT& operator = ( const PointT&    v ) {
      if ( this != &v ) {
        x = v.x; y = v.y;
      } return *this;
    }

    PointT& operator +=( const PointT&    v ) {
      x += v.x; y += v.y; return *this;
    }
    PointT& operator -=( const PointT&    v ) {
      x -= v.x; y -= v.y; return *this;
    }
    PointT& operator +=( const scalar_type  s ) {
      x += s;   y += s;   return *this;
    }
    PointT& operator -=( const scalar_type  s ) {
      x -= s;   y -= s;   return *this;
    }
    PointT& operator /=( const scalar_type  s ) {
      x /= s;   y /= s;   return *this;
    }
    PointT& operator *=( const scalar_type  s ) {
      x *= s;   y *= s;   return *this;
    }
    PointT& scale( const scalar_type  s ) {
      return ( *this ) *= s;
    }

    PointT operator +( const scalar_type s )  const {
      return PointT( x + s, y + s );
    }
    PointT operator -( const scalar_type s )  const {
      return PointT( x - s, y - s );
    }
    PointT operator *( const scalar_type s )  const {
      return PointT( x * s, y * s );
    }
    PointT operator /( const scalar_type s )  const {
      return PointT( x / s, y / s );
    }
    PointT operator +( const PointT&   v )  const {
      return PointT( x + v.x, y + v.y );
    }
    PointT operator -( const PointT&   v )  const {
      return PointT( x - v.x, y - v.y );
    }
    PointT operator -()                       const {
      return PointT( -x, -y );
    }

    PointT& offset( const scalar_type x, const scalar_type y )
    {
      this->x += x;
      this->y += y;

      return *this;
    }

    bool operator==( const PointT&   v )  const {
      return  x == v.x && y == v.y;
    }
    bool operator!=( const PointT&   v )  const {
      return  !operator==( v );
    }

    bool operator< ( const PointT&   v ) const
    {
      return ( x < v.x ||
               !( v.x < x ) && y < v.y );
    }

    PointT& RotateZ( const double angle )
    {
      PointT vTemp( *this );
      double w( angle * double( 3.1415926535 / 180 ) );
      x = T( vTemp.x * cos( w ) - vTemp.y * sin( w ) );
      y = T( vTemp.x * sin( w ) + vTemp.y * cos( w ) );
      return *this;
    }

    float length()                              const
    {
      return sqrtf( (float)length_squared() );
    }

    scalar_type length_squared()                const
    {
      return x * x + y * y;
    }

    scalar_type perpendicular( const PointT& v2 ) const
    {
      return x * v2.y - y * v2.x;
    }

    float dot( const PointT& v ) const
    {
      return (float)x * (float)v.x + (float)y * (float)v.y;
    }

  };

  typedef PointT<int>     Point;
  typedef PointT<float>   PointF;

};




#endif // LD_TYPES_H