/*
  File name: CSDLClass.h
  Copyright: (C) 2005 - 2013 Tomasz Kazmierczak

  This file is part of Cytadela

 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program. If not, see <http://www.gnu.org/licenses/>.  *

*/

#ifndef _CSDLCLASS_H_
#define _CSDLCLASS_H_

#include <SDL/SDL.h>
#include <SDL/SDL_mixer.h>
#include "farread.h"

#define CSDL_DEFAULT_SCREEN_W      640
#define CSDL_DEFAULT_SCREEN_H      480
#define CSDL_DEFAULT_SCREEN_W_TXT  "640"
#define CSDL_DEFAULT_SCREEN_H_TXT  "480"

#define CSDL_LOAD_SOUND_FAILED     -1
#define CSDL_AUDIO_NOT_INITIALIZED -2

class ScreenSize {
public:
	const char *resolutionString[2];
	int32_t     resolution[2];
	bool        available;
};

class CSDLClass;

class CImagesArray {
friend class CSDLClass;
private:
	SDL_Surface **mImageSurface;
	ImgDims      *mImageDims;
	uint32_t      mImagesCount;
public:

	CImagesArray() :  mImageSurface(0), mImageDims(0), mImagesCount(0) {};
	~CImagesArray() { free(); }

	void free();
	bool loadImg(const char* farFileName, const char* imgFileName, uint32_t &imgNum);

	const ImgDims *getImageDimensions(uint32_t imageNum);
};

typedef class {
public:
	SDLKey key[5];     //eKey and bStatus are used to handle key up/down events
	bool   status[5];  // which just occured (we could use pKeyMap for this,
	                   // but then we would have to check the previous key map
	                   // status - it is much simplier to just check for events
	                   // which have just occured) - good to handle options
	                   // switching
	uint8_t *keyMap;   //pressed/unpressed keys state - a good way to handle
	                   // player's
	                   //movement and weapons/tools usage
	int16_t mouseX;
	int16_t mouseY;
	bool    lmb;
	bool    rmb;
	bool    joyButtonPressed;
	bool    joyUp;
	bool    joyDown;
	bool    joyLeft;
	bool    joyRight;
} InputArray;

//don't need more sounds, and fixed size array is easier to handle than dynamical one
#define MAX_SOUNDS_COUNT     25

class CSDLClass {
public:
	enum VideoMode { Mode2D, Mode3D };
	enum ScreenMode { FullScreen, Windowed, NoChange };

private:
	SDL_Surface  *mScreen;
	SDL_Joystick *mJoystick;
	Mix_Music    *mMusic;
	Mix_Chunk    *mSounds[MAX_SOUNDS_COUNT];
	bool          mAudioAvailable;
	bool          mAudioEnabled;
	int32_t       mLoadedSoundsCount;
	int16_t       mMenuMouseXPos;
	int16_t       mMenuMouseYPos;
	uint32_t      mLastMouseInputTime;
	uint32_t      mLastJoyInputTime;

	int32_t     mScreenSizesCount;
	ScreenSize *mScreenSizes;
	ScreenMode  mScreenMode;

	CSDLClass();
	~CSDLClass() { free(); }
public:
	CImagesArray mImgArray;

	static CSDLClass *instance();

	//init/free
	bool init();
	void free();
	bool switchVideoMode(int32_t width, int32_t height, VideoMode vmode, ScreenMode smode = NoChange);

	//input
	void delayInput();
	void clearEventQueue();
	SDLKey readInputMenu();
	void readInputGame(InputArray *inputArray);

	//time
	uint32_t getTicks() { return SDL_GetTicks(); }

	void delay(uint32_t miliseconds) { SDL_Delay(miliseconds); }

	//display
	void displayImage(uint32_t imgNum, SDL_Rect *srcRect, int16_t x, int16_t y);
	void displayText(uint32_t imgNum, const char *text, int16_t x, int16_t y);
	void blackScreen();
	void drawFrame() { SDL_Flip(mScreen); }
	void swapBuffers() { SDL_GL_SwapBuffers(); }
	int32_t getScreenSizesCount() { return mScreenSizesCount; }
	const ScreenSize *getScreenSizes() { return mScreenSizes; }
	int32_t findFirstAvailableScreenSize(int32_t start);

	//audio
	bool loadMusic(const char *fileName);
	void freeMusic();
	void playMusic(int32_t loops);
	void stopMusic();
	int32_t loadSound(const char *fileName);
	void freeSounds();
	void playSoundFadeIn(int32_t sound, int32_t channel, int32_t loops, int32_t fadeInTime);
	void playSound(int32_t sound, int32_t channel, int32_t volume = 126, int32_t loops = 0);
	void setSoundVolume(int32_t channel, int32_t volume);
	void stopSound(int32_t channel, int32_t fadeOutTime);
	bool isAudioEnabled();
	void setAudioEnabled(bool enabled);

	//video
	bool playVideo(const char *fileName, bool offOnFinish, bool audio);
};

#endif
