/* vim: ts=4 sw=4 sts=4 :
 * =============================================================================
 *  SDL sample  for  D
 * =============================================================================
 */

import std.stdio;
import std.string;
import std.conv;
import std.c.stdlib;

import sdl.c.sdl;
import sdl.c.sdl_ttf;


/**
 * MAIN.
 *
 * Params:
 *  args = 起動引数
 */
int main(char[][] args)
{

	SDLTtf sdlttf = new SDLTtf();
	sdlttf.showFont("Sample");
	eventLoop();

	return 0;
}


/**
 * イベントループ.
 */
void eventLoop()
{
	int quit = 0;
	SDL_Event event;

	/* unicode 変換を有効にする. */
	SDL_EnableUNICODE(1);

	while (!quit)
	{
		while (SDL_PollEvent(&event))
		{
			switch (event.type)
			{
				/* SDL_QUIT イベント (ウィンドウが閉じられた) */
				case SDL_QUIT:
					quit = 1;
					break;

				default:
					break;
			}
		}
	}
}


/**
 * SDLMixer.
 * あくまでサンプル, 構成変でスミマセン.
 */
class SDLTtf
{
	/**
	 * 静的コンストラクタ.
	 *
	 * SDL_Init を実行し, SDL を初期化しています.
	 * SDL_Init 実行後, まだ初期化していないサブシステムを
	 * 初期化する場合は, SDL_InitSubSytem を使用する必要があります.
	 */
	static this()
	{
		int ret = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
		if (ret < 0)
		{	// SDL初期化失敗
			string errmsg = getErrorMessage();
			throw new SDLException("can't init sdl. " ~ errmsg);
		}
	}


	/**
	 * 静的デストラクタ.
	 * static this() が正常に完了している場合にのみ,
	 * プログラム終了時に呼び出されます.
	 * 本デストラクタにて, SDL終了処理を実行しています.
	 */
	static ~this()
	{
		SDL_Quit();
	}


	/**
	 * コンストラクタ.
	 * ビデオ表示初期化等を実施します.
	 */
	public
	this()
	{
		this.screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);
		if (this.screen is null)
		{	// Video Mode 設定失敗
			string errmsg = getErrorMessage();
			throw new SDLException("can't set video mode. " ~ errmsg);
		}
	}


	/**
	 * メディア再生.
	 *
	 * Params:
	 *  msg = メッセージ
	 */
	public void showFont(string msg)
	{
		// TTF 初期化
		int ret = TTF_Init();
		if (ret != 0)
		{
			string errmsg = getErrorMessage();
			throw new SDLException("can't init ttf. " ~ errmsg);
		}

		// フォントファイルオープン
		string    fontName = getFontFile();
		TTF_Font* font     = TTF_OpenFont(
			cast(char*) std.string.toStringz(fontName), 12);
		if (font is null)
		{	// フォントファイルオープンエラー
			string errmsg = getErrorMessage();
			throw new SDLException("can't open font. " ~ errmsg);
		}

		// 文字設定
		SDL_Color color = { 0, 0, 255, 0};
		SDL_Surface* txtSurface = TTF_RenderUTF8_Solid(
			font, cast(char*) std.string.toStringz(msg), color);

		SDL_Rect dest;
		dest.x = 0;
		dest.y = 0;
		SDL_BlitSurface(txtSurface, null, this.screen, &dest);

		// 画面更新
		SDL_Flip(this.screen);
	}


	/**
	 * 現在発生している SDL エラーメッセージを取得します.
	 *
	 * Returns:
	 *  エラーメッセージ
	 */
	public static
	string getErrorMessage()
	{
		const char* errmsg = SDL_GetError();
		return std.string.toString(errmsg);
	}


	/**
	 * フォントファイル取得.
	 */
	private string getFontFile()
	{
		char* path = std.c.stdlib.getenv("SystemRoot");
		string fontfile = std.string.toString(path);
		fontfile ~= "/Fonts/arial.ttf";
		return cast(string) fontfile;
	}


	private
	{
		SDL_Surface* screen;
	}

}


/**
 * SDL Exception.
 * エラー発生時に throw する.
 */
class SDLException : Exception
{
	/**
	 * 指定されたエラーメッセージを持つ, SDLException を構築します.
	 *
	 * Params:
	 *   msg  = エラーメッセージ
	 *   next = Exception
	 */
    this(string msg, Throwable next = null)
    {
        super(msg, next);
    }
}

