module kyojintati4d.component.ending.movieproxy;

private import SDL;
private import SDL_smpeg;

private import y4d;
private import y4d_aux.filesys;

private import kyojintati4d.myapp;
private import kyojintati4d.gameinfo;

private import yamalib.draw.movie;
private import yamalib.log.log;

public class MovieProxy {
	
	/** 初期化 */
	void onLoad(char[] filename, bool loopFlg, float volume) {
		// メモリー状況をプリント
		GameInfo.printMemoryState();
		Log.print("create Instance");
		
		/** 再生しているものをリリース */
		release();

		{
			Log.print("load movie file");
			if (y4d_result.no_error != movie.load(filename, false) ) {;
				Log.printError("load error");
			}
			
			if (viewTexture !is null) {
				viewTexture.release();
			}
			
			viewTexture = new Texture();
			Log.print("set texture");
			// サーフェイスを喰わせてテクスチャを予約する
			viewTexture.setSurface(movie.surface.clone());
			Log.print("set loop true");
			movie.isLoop = loopFlg;
			movie.volume = volume;
		}
		
		init = true;
		Log.print("onInit finish");
	}

	/// 再生する
	void play() {
		if (movie !is null) {
			movie.play();
		}
	}
	
	/// 停止する
	void stop() {
		if (movie !is null) {
			movie.stop();
		}
	}
	
	/// 一時停止
	void pause() {
		if (movie !is null) {
			movie.pause();
		}
	}

	/** 描画の処理を行います */
	Texture getTexture() {
		try {
			if (!init) {
				return null;
			}
			
			if (movie.isReadyToDraw) 
			{
				if (getMyMovieState.updated) {
					// まずテクスチャにする
					movie.draw(viewTexture);
				}
				getMyMovieState.updated = false;
			}

			return viewTexture;
		} catch (Exception e) {
			Log.printFatal("RuntimeException %s#onDraw : [%s] [%s]", 
				super.toString(), e.toString(), e.msg);
			throw e;
		}
	}
	
	/** 再生しているか */
	bool isPlaying() {
		return movie.isPlaying();
	}

	/// 占有しているメモリを解放する
	void release() {
		if (movie !is null) {
			movie.release();
		}
		Log.print("%s#destroy : destroyed.", super.toString());
	}

	/** コンストラクタ */
	this() {
		movieState = new MovieState();
		movie = new Movie(getMyCallbacker(), getMyMovieState());
	}
	
	
protected:
	
	/// このクラスをコピーするときはオーバーライドすること！
	SMPEG_DisplayCallback getMyCallbacker() {
		return cast(SMPEG_DisplayCallback) &smpeg_DisplayCallback1;
	}
	
	/// このクラスをコピーするときはオーバーライドすること！
	MovieState getMyMovieState() {
		return movieState;
	}
	
private:
	/// <summary>
	/// 描画時に呼び出されるコールバック関数。
	/// 別スレッドらしいので、GL周りの処理とかは止めとくのが無難っぽい。
	/// </summary>
	extern (C) static void smpeg_DisplayCallback1(SDL_Surface* dst, int x, int y, uint w, uint h)
	{
		Rect rc;
		rc.setRect(x, y, cast(int) w, cast(int) h);
		movieState.updateRect = rc;
		movieState.updated = true;
		// readyToDraw = true; // 一度でも描画されたら描画準備完了と見なす。
		if (!movieState.readyToDraw)
			
		{
			// 全面が更新されたら描画準備完了
//			Rect* r = &m_updateRect;
//			if (width <= r.getWidth && height <= r.getHeight)
			{
				movieState.readyToDraw = true;
			}
		}
	}

private:
	bool init = false;
	
	Movie movie;
	Texture viewTexture;
	static MovieState movieState;
}

public class MovieProxy2 : MovieProxy {
public:
	/** コンストラクタ */
	this() {
		movieState2 = new MovieState();
		movie = new Movie(getMyCallbacker(), getMyMovieState());
	}

protected:
		
	/// このクラスをコピーするときはオーバーライドすること！
	SMPEG_DisplayCallback getMyCallbacker() {
		return cast(SMPEG_DisplayCallback) &smpeg_DisplayCallback2;
	}
	
	/// このクラスをコピーするときはオーバーライドすること！
	MovieState getMyMovieState() {
		return movieState2;
	}

private:
	/// <summary>
	/// 描画時に呼び出されるコールバック関数。
	/// 別スレッドらしいので、GL周りの処理とかは止めとくのが無難っぽい。
	/// </summary>
	extern (C) static void smpeg_DisplayCallback2(SDL_Surface* dst, int x, int y, uint w, uint h)
	{
		Rect rc;
		rc.setRect(x, y, cast(int) w, cast(int) h);
		movieState2.updateRect = rc;
		movieState2.updated = true;
		// readyToDraw = true; // 一度でも描画されたら描画準備完了と見なす。
		if (!movieState2.readyToDraw)
			
		{
			// 全面が更新されたら描画準備完了
//					Rect* r = &m_updateRect;
//					if (width <= r.getWidth && height <= r.getHeight)
			{
				movieState2.readyToDraw = true;
			}
		}
	}
	
	static MovieState movieState2;
}

