#ifndef __MODULE_SDL_H__
#define __MODULE_SDL_H__

#include <ascript.h>
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_mixer.h>
//#include <SDL_ttf.h>

#undef LoadImage

#define SDL_USEREVENT_Timer (SDL_NUMEVENTS - 1)

AScript_BeginModule(sdl)

const char *GetEventTypeName(Uint8 type);

//-----------------------------------------------------------------------------
// Object_Cursor declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Cursor);

class Object_Cursor : public Object {
public:
	AScript_DeclareObjectAccessor(Cursor)
private:
	SDL_Cursor *_pCursor;
public:
	inline Object_Cursor(SDL_Cursor *pCursor) :
			Object(AScript_PrivClass(Cursor)), _pCursor(pCursor) {}
	inline Object_Cursor(const Object_Cursor &obj) : Object(obj) {}
	virtual ~Object_Cursor();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	void FreeCursor();
	inline SDL_Cursor *GetCursor() { return _pCursor; }
	inline static Value CreateValue(SDL_Cursor *pCursor) {
		return Value(new Object_Cursor(pCursor));
	}
};

//-----------------------------------------------------------------------------
// Object_Timer declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Timer);

class Object_Timer : public Object {
public:
	AScript_DeclareObjectAccessor(Timer)
private:
	SDL_TimerID _timerID;
	Signal _sig;
	Object_Function *_pObjFunc;
	bool _threadFlag;
	bool _contFlag;
public:
	inline Object_Timer(Signal sig, Object_Function *pObjFunc, bool threadFlag) :
		Object(AScript_PrivClass(Timer)), _timerID(NULL),
		_sig(sig), _pObjFunc(pObjFunc), _threadFlag(threadFlag), _contFlag(false) {}
	virtual ~Object_Timer();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	inline bool IsThread() const { return _threadFlag; }
	bool AddTimer(Uint32 interval);
	bool RemoveTimer();
	bool DoHandle();
	static Uint32 CallbackStub(Uint32 interval, void *param);
};

//-----------------------------------------------------------------------------
// Object_Event declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Event);

class Object_Event : public Object {
public:
	AScript_DeclareObjectAccessor(Event)
private:
	SDL_Event _event;
public:
	inline Object_Event(SDL_Event event) :
					Object(AScript_PrivClass(Event)), _event(event) {}
	inline Object_Event(const Object_Event &obj) : Object(obj) {}
	virtual ~Object_Event();
	virtual Object *Clone() const;
	virtual Value DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag);
	virtual String ToString(Signal sig, bool exprFlag);
	inline SDL_Event &GetEvent() { return _event; }
	inline const SDL_Event &GetEvent() const { return _event; }
	inline static Value CreateValue(const SDL_Event &event) {
		return Value(new Object_Event(event));
	}
};

//-----------------------------------------------------------------------------
// Object_Rect declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Rect);

class Object_Rect : public Object {
public:
	AScript_DeclareObjectAccessor(Rect)
private:
	SDL_Rect _rect;
public:
	inline Object_Rect(const SDL_Rect &rect) :
			Object(AScript_PrivClass(Rect)), _rect(rect) {}
	inline Object_Rect(const Object_Rect &obj) : Object(obj) {}
	virtual ~Object_Rect();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	virtual Value DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag);
	inline SDL_Rect &GetRect() { return _rect; }
	inline const SDL_Rect &GetRect() const { return _rect; }
	inline static Value CreateValue(const SDL_Rect &rect) {
		return Value(new Object_Rect(rect));
	}
};

//-----------------------------------------------------------------------------
// Object_Color declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Color);

class Object_Color : public Object {
public:
	AScript_DeclareObjectAccessor(Color)
private:
	SDL_Color _color;
public:
	inline Object_Color(const SDL_Color &color) :
			Object(AScript_PrivClass(Color)), _color(color) {}
	inline Object_Color(const Object_Color &obj) : Object(obj) {}
	virtual ~Object_Color();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	virtual Value DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag);
	inline SDL_Color &GetColor() { return _color; }
	inline const SDL_Color &GetColor() const { return _color; }
	inline static Value CreateValue(const SDL_Color &color) {
		return Value(new Object_Color(color));
	}
};

//-----------------------------------------------------------------------------
// Object_Palette declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Palette);

class Object_Palette : public Object {
public:
	AScript_DeclareObjectAccessor(Palette)
private:
	const SDL_Palette *_pPalette;
public:
	inline Object_Palette(const SDL_Palette *pPalette) :
			Object(AScript_PrivClass(Palette)), _pPalette(pPalette) {}
	inline Object_Palette(const Object_Palette &obj) : Object(obj) {}
	virtual ~Object_Palette();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	virtual Value DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag);
	inline static Value CreateValue(const SDL_Palette *pPalette) {
		return Value(new Object_Palette(pPalette));
	}
};

//-----------------------------------------------------------------------------
// Object_PixelFormat declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(PixelFormat);

class Object_PixelFormat : public Object {
public:
	AScript_DeclareObjectAccessor(PixelFormat)
private:
	SDL_PixelFormat _pixelFormat;
public:
	Object_PixelFormat(const SDL_PixelFormat &pixelFormat);
	inline Object_PixelFormat(const Object_PixelFormat &obj) : Object(obj) {}
	virtual ~Object_PixelFormat();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	virtual Value DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag);
	inline SDL_PixelFormat *GetPixelFormat() { return &_pixelFormat; }
	inline const SDL_PixelFormat *GetPixelFormat() const { return &_pixelFormat; }
	inline static Value CreateValue(const SDL_PixelFormat &pixelFormat) {
		return Value(new Object_PixelFormat(pixelFormat));
	}
};

//-----------------------------------------------------------------------------
// Object_PixelFormat declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Surface);

class Object_Surface : public Object {
public:
	AScript_DeclareObjectAccessor(Surface)
private:
	SDL_Surface *_pSurface;
	Object *_pObjRef;
public:
	inline Object_Surface(SDL_Surface *pSurface) :
				Object(AScript_PrivClass(Surface)), _pSurface(pSurface), _pObjRef(NULL) {}
	inline Object_Surface(const Object_Surface &obj) : Object(obj),
				_pObjRef(Object::Reference(obj._pObjRef)) {}
	inline SDL_Surface *GetSurface() { return _pSurface; }
	virtual ~Object_Surface();
	virtual Object *Clone() const;
	virtual Value DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag);
	virtual String ToString(Signal sig, bool exprFlag);
	inline void SetReferenceObject(Object *pObj) { _pObjRef = pObj; }
	inline static Value CreateValue(SDL_Surface *pSurface) {
		return Value(new Object_Surface(pSurface));
	}
	static Object_Surface *CreateSurfaceFromImage(Signal sig, Object_Image *pObjImg);
};

//-----------------------------------------------------------------------------
// Object_Overlay declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Overlay);

class Object_Overlay : public Object {
public:
	AScript_DeclareObjectAccessor(Overlay)
private:
	SDL_Overlay *_pOverlay;
public:
	inline Object_Overlay(SDL_Overlay *pOverlay) :
				Object(AScript_PrivClass(Overlay)), _pOverlay(pOverlay) {}
	inline Object_Overlay(const Object_Overlay &obj) : Object(obj) {}
	inline SDL_Overlay *GetOverlay() { return _pOverlay; }
	virtual ~Object_Overlay();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	inline static Value CreateValue(SDL_Overlay *pOverlay) {
		return Value(new Object_Overlay(pOverlay));
	}
};

//-----------------------------------------------------------------------------
// Object_VideoInfo declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(VideoInfo);

class Object_VideoInfo : public Object {
public:
	AScript_DeclareObjectAccessor(VideoInfo)
private:
	const SDL_VideoInfo *_pVideoInfo;
public:
	inline Object_VideoInfo(const SDL_VideoInfo *pVideoInfo) :
			Object(AScript_PrivClass(VideoInfo)), _pVideoInfo(pVideoInfo) {}
	inline Object_VideoInfo(const Object_VideoInfo &obj) : Object(obj) {}
	virtual ~Object_VideoInfo();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	virtual Value DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag);
	inline static Value CreateValue(const SDL_VideoInfo *pVideoInfo) {
		return Value(new Object_VideoInfo(pVideoInfo));
	}
};

#if 0
//-----------------------------------------------------------------------------
// Object_Font declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Font);

class Object_Font : public Object {
public:
	AScript_DeclareObjectAccessor(Font)
private:
	TTF_Font *_pFont;
public:
	inline Object_Font(TTF_Font *pFont) :
			Object(AScript_PrivClass(Font)), _pFont(pFont) {}
	inline Object_Font(const Object_Font &obj) : Object(obj) {}
	virtual ~Object_Font();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	inline TTF_Font *GetFont() { return _pFont; }
	inline static Value CreateValue(TTF_Font *pFont) {
		return Value(new Object_Font(pFont));
	}
};
#endif

//-----------------------------------------------------------------------------
// Object_Joystick declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(Joystick);

class Object_Joystick : public Object {
public:
	AScript_DeclareObjectAccessor(Joystick)
private:
	SDL_Joystick *_pJoystick;
public:
	inline Object_Joystick(SDL_Joystick *pJoystick) :
			Object(AScript_PrivClass(Joystick)), _pJoystick(pJoystick) {}
	inline Object_Joystick(const Object_Joystick &obj) : Object(obj) {}
	virtual ~Object_Joystick();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	inline SDL_Joystick *GetJoystick() { return _pJoystick; }
	inline static Value CreateValue(SDL_Joystick *pJoystick) {
		return Value(new Object_Joystick(pJoystick));
	}
};

//-----------------------------------------------------------------------------
// Object_AudioSpec declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(AudioSpec);

class Object_AudioSpec : public Object {
public:
	AScript_DeclareObjectAccessor(AudioSpec)
private:
	SDL_AudioSpec *_pAudioSpec;
	Signal *_pSig;
	Function *_pFuncCallback;
	Uint8 *_audio_buf;
	Uint32 _audio_len;
public:
	inline Object_AudioSpec(SDL_AudioSpec *pAudioSpec,
		Signal *pSig, Function *pFuncCallback, Uint8 *audio_buf, Uint32 audio_len) :
			Object(AScript_PrivClass(AudioSpec)),
			_pAudioSpec(pAudioSpec), _pSig(pSig), _pFuncCallback(pFuncCallback),
			_audio_buf(audio_buf), _audio_len(audio_len) {}
	inline Object_AudioSpec(const Object_AudioSpec &obj) : Object(obj) {}
	virtual ~Object_AudioSpec();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	inline SDL_AudioSpec *GetAudioSpec() { return _pAudioSpec; }
	inline Uint8 *GetAudioBuf() { return _audio_buf; }
	inline Uint32 GetAudioLen() { return _audio_len; }
	inline static Value CreateValue(SDL_AudioSpec *pAudioSpec,
			Signal *pSig,  Function *pFuncCallback, Uint8 *audio_buf, Uint32 audio_len) {
		return Value(new Object_AudioSpec(pAudioSpec, pSig, pFuncCallback, audio_buf, audio_len));
	}
	void Callback(Uint8 *stream, int len);
	static void CallbackStub(void *userdata, Uint8 *stream, int len);
};

//-----------------------------------------------------------------------------
// Object_AudioCVT declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(AudioCVT);

class Object_AudioCVT : public Object {
public:
	AScript_DeclareObjectAccessor(AudioCVT)
private:
	SDL_AudioCVT *_pAudioCVT;
public:
	inline Object_AudioCVT(SDL_AudioCVT *pAudioCVT) :
			Object(AScript_PrivClass(AudioCVT)), _pAudioCVT(pAudioCVT) {}
	inline Object_AudioCVT(const Object_AudioCVT &obj) : Object(obj) {}
	virtual ~Object_AudioCVT();
	virtual Object *Clone() const;
	virtual String ToString(Signal sig, bool exprFlag);
	inline SDL_AudioCVT *GetAudioCVT() { return _pAudioCVT; }
	inline static Value CreateValue(SDL_AudioCVT *pAudioCVT) {
		return Value(new Object_AudioCVT(pAudioCVT));
	}
};

//-----------------------------------------------------------------------------
// Object_CDtrack declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(CDtrack);

class Object_CDtrack : public Object {
public:
	AScript_DeclareObjectAccessor(CDtrack)
private:
	SDL_CDtrack _CDtrack;
public:
	inline Object_CDtrack(const SDL_CDtrack &CDtrack) : Object(AScript_PrivClass(CDtrack)), _CDtrack(CDtrack) {}
	inline Object_CDtrack(const Object_CDtrack &obj) : Object(obj) {}
	virtual ~Object_CDtrack();
	virtual Object *Clone() const;
	virtual Value DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag);
	virtual String ToString(Signal sig, bool exprFlag);
	inline SDL_CDtrack &GetCDtrack() { return _CDtrack; }
	inline static Value CreateValue(const SDL_CDtrack &CDtrack) {
		return Value(new Object_CDtrack(CDtrack));
	}
};

//-----------------------------------------------------------------------------
// Object_CD declaration
//-----------------------------------------------------------------------------
AScript_DeclarePrivClass(CD);

class Object_CD : public Object {
public:
	AScript_DeclareObjectAccessor(CD)
private:
	SDL_CD *_pCD;
public:
	inline Object_CD(SDL_CD *pCD) : Object(AScript_PrivClass(CD)), _pCD(pCD) {}
	inline Object_CD(const Object_CD &obj) : Object(obj) {}
	virtual ~Object_CD();
	virtual Object *Clone() const;
	virtual Value DoPropGet(Signal sig, const Symbol *pSymbol, bool &evaluatedFlag);
	virtual String ToString(Signal sig, bool exprFlag);
	inline SDL_CD *GetCD() { return _pCD; }
	inline static Value CreateValue(SDL_CD *pCD) {
		return Value(new Object_CD(pCD));
	}
};

}}

#endif
