// TiSprite.h
// Created by Jon Wiesman
// Yet another 2D image/animation class.  I belive this is the fifth one I've done in 5 years.

#ifndef __TiSprite_h__
#define __TiSprite_h__

#include "SyTypes.h"
#include "SyResourceID.h"
#include "TiPtSizeRect.h"
#include "TiFPtSizeRect.h"
#include "SyTime.h"
#include <map>

///////////////////////////////////////////////////////////////////////////////
//
// TiSpriteFrame
//
///////////////////////////////////////////////////////////////////////////////

class TiSpriteFrame
{
    SyResourceID    m_uHashId;
    TiPoint         m_ptHotspot;
    TiRect          m_rectSource;
    float32         m_fDuration;
    mutable int32   m_nSurfaceId;
    mutable TiPoint m_ptAtlasOffset;


// static members for the pool
    enum 
    {
        SF_SpriteFrameCount = 1024,
        SF_InvalidSurfaceId = -1,
    };
    static int32            sm_nNextFrame;
    static TiSpriteFrame    sm_arPool[SF_SpriteFrameCount];
    static TiSpriteFrame    *AllocFrame();
    static void             ClearAll();
    
    void                    Init();

public:
    TiSpriteFrame();

    int32       GetSurfaceId() const;

    friend class TiSpriteInfo;
    friend class TiSprite;
};

///////////////////////////////////////////////////////////////////////////////
//
// TiSpriteInfo
//
///////////////////////////////////////////////////////////////////////////////

class TiBitmapInfo;

class TiSpriteInfo
{
    SyResourceID    m_uId;
    int32           m_nCount;
    float32         m_fTotalDuration;
    TiSpriteFrame   *m_arFrames;  


// static members for pool
    enum 
    {
        SIP_SpriteInfoCount = 768,
    };
    static int32        sm_nNextSprite;
    static TiSpriteInfo sm_arPool[SIP_SpriteInfoCount];
    static TiSpriteInfo *AllocSprite();

    void                Init();

public:
    TiSpriteInfo();

    const TiSpriteFrame *GetFrameFromStart(float32 fOffsetTime, bool bLoop = true) const;

    TiSize              GetSize() const;
    SyResourceID        GetID() const {return m_uId;}


    static void         ReadXML(const char8 *pszFilename);
    static void         CreateTextureSprites(std::map< SyResourceID, TiBitmapInfo > &mapAtlasDirectory);
    static TiSpriteInfo *FindSprite(uint32 uId);
    static TiSpriteInfo *FindSprite(const char8 *pszName);
    static void         ClearAll();
};


///////////////////////////////////////////////////////////////////////////////
//
// TiSprite
//
///////////////////////////////////////////////////////////////////////////////

class TiSprite
{
    mutable TiSpriteInfo *m_pInfo;  // this is very upsetting, but necessary
    mutable int32         m_iReload;

    SyResourceID          m_idSpriteInfo;
    float32               m_fStartTime;
    bool                  m_bLoop;

    static int32          sm_nReloadCount;
    static float          sm_fAnimationTime;

public:
    TiSprite() {m_pInfo = NULL; m_fStartTime = 0.0f; m_bLoop = true;}
    ~TiSprite() {}

    void                ResetInfo() {m_pInfo = NULL;}
    void                SetInfo(TiSpriteInfo *pInfo);
    void                SetInfo(SyResourceID uId);
    void                SetInfo(const char8 *psz);
    void                Restart() {m_fStartTime = sm_fAnimationTime;}
    void                SetLooping(bool bLoop = true) {m_bLoop = bLoop;}


    TiSize              GetSize() const;
    bool                IsEmpty() const {return m_pInfo == NULL;}
    int32               PrepareRects(TiPoint pt, TiRect rectClip, TiRect &rectSrc, TiRect &rectOS) const;
    int32               PrepareRects(TiRect rectOSIn, TiRect rectClip, TiRect &rectSrc, TiRect &rectOS) const;
    int32               PrepareRects(TiFRect rectOSIn, TiRect rectClip, TiRect &rectSrc, TiFRect &rectOS) const;

    void                VerifySpriteInfo() const;
    int32               Draw(const TiPoint &pt, const TiRect &rectClip = c_rectPS3Screen, float32 fOpacity = 1.0f) const;
    int32               Tile(const TiRect &rect, const TiRect &rectClip = c_rectPS3Screen, float32 fOpacity = 1.0f) const;
    int32               Stretch(const TiRect &rect, const TiRect &rectClip = c_rectPS3Screen, float32 fOpacity = 1.0f) const;
    int32               Pulse(TiRect rect, float32 fMagnitude, float32 fSpeed = 2.f * SY_PI, const TiRect &rectClip = c_rectPS3Screen, float32 fOpacity = 1.0f) const;
    int32               Oscillate(TiPoint pt1, TiPoint pt2, float32 fSpeed = 2.f * SY_PI, TiRect rectClip = c_rectPS3Screen, float32 fOpacity = 1.f) const;
    // float versions
    int32               Stretch(const TiFRect &rect, const TiRect &rectClip = c_rectPS3Screen, float32 fOpacity = 1.0f) const;
    int32               Pulse(TiFRect rect, float32 fMagnitude, float32 fSpeed = 2.f * SY_PI, const TiRect &rectClip = c_rectPS3Screen, float32 fOpacity = 1.0f) const;


    static void         UpdateAnimationTime(float32 fElapsed);
    static void         UpdateAnimationTime(SyTime time);
    static void         ForceReload();
};



#endif

