module kyojintati4d.component.ending.MoviePlayer;

private import std.stream;

private import y4d;
private import y4d_aux.filesys;
private import y4d_aux.lineparser;

private import kyojintati4d.component.ending.movieproxy;

private import yamalib.counterfsp;
private import yamalib.log.log;

class MovieFileInfo {

	/** 定義ファイルより、MovieFileInfoを生成し返却する */
	static MovieFileInfo[]	createFromDefFile(char[] defFilename) {
		ubyte[] mem = cast(ubyte[])(FileSys.read(defFilename));
		if (!mem) return null; // 読み込みエラー
		auto m = new std.stream.MemoryStream(mem);
		LineParser lp = new LineParser();

		MovieFileInfo[] result;
		
		while (!m.eof) {
			char[] linebuf = cast(char[]) m.readLine();
			lp.setLine(linebuf);
			
			// ファイル名
			auto filename = lp.getStr();
			if (!filename) continue; // ダメやん

			auto instance = new MovieFileInfo(filename);

			// 再生ミリ秒
			instance.length = lp.getNum(-1);
			// 基本α
			instance.baseAlpha = lp.getNum(255);
			// ランダム加算値
			instance.randAlpha = lp.getNum(1);
			// インターバル
			instance.interval = lp.getNum(0);
			// 評価
			instance.rate = lp.getNum(0);
			
			
			result ~= instance;
		}
		return result;
	}
	
	/** コンストラクタ */
	this(char[] movieFilename) {
		m_movieTmpFile = FileSys.getTmpFile(movieFilename);
		m_filename = m_movieTmpFile.getFileName();
		assert(m_filename !is null);
Log.print("MOVIE FILENAME:%s", m_filename);
		m_fadeinAlphaCounter = new RootCounterS();
		m_fadeinAlphaCounter.set(0, 192, 10);
		m_fadeoutAlphaCounter = new RootCounterS();
		m_fadeoutAlphaCounter.set(192, 0, 10);
	}
	
	/** デストラクタ */
	~this() {
		release();
	}

	/** 解放処理 */
	void release() {
		if (m_movieTmpFile !is null) {
			m_movieTmpFile.release();
		}
	}
	
	/** ファイル名 */
	char[] filename() {
		return m_filename;
	}
	
	/** ムービーの再生ミリ秒 */
	uint length() {
		return m_length;
	}
	uint length(uint value) {
		return m_length = value;
	}
	
	/** 基本となる描画時のα値 */
	int baseAlpha() {
		return m_baseAlpha;
	}
	int baseAlpha(int value) {
		return m_baseAlpha = value;
	}
	
	/** baseAlphaにランダムで加算する最大αの設定 */
	int randAlpha() {
		return m_randAlpha;
	}
	int randAlpha(int value) {
		return m_randAlpha = value;
	}
	
	/** 再生開始時にいれるインターバル（待機時間） */
	int interval() {
		return m_interval;
	}
	int interval(int value) {
		return m_interval = value;
	}
	
	/** 評価値 */
	long rate() {
		return m_rate;
	}
	long rate(long value) {
		return m_rate = value;
	}
	
	/** フェードイン用のαカウンタ。baseAlphaｓを設定してもこの開始値・終了値は変更しない */
	RootCounterS fadeinAlphaCounter() {
		return m_fadeinAlphaCounter;
	}
	/** フェードアウト用のαカウンタ。baseAlphaｓを設定してもこの開始値・終了値は変更しない */
	RootCounterS fadeoutAlphaCounter() {
		return m_fadeoutAlphaCounter;
	}
	
private:
	/** ファイル名 */
	final char[] m_filename;
	/** 展開の必要が有れば展開 */
	FileSys.TmpFile m_movieTmpFile;
	/** ミリ秒 */
	uint m_length;
	/** 基本とするα値 */
	int m_baseAlpha;
	/** ランダムで使用する最大加算値 */
	int m_randAlpha = 1;
	/** フェードイン・アウトに使用するカウンタ */
	RootCounterS m_fadeinAlphaCounter;
	RootCounterS m_fadeoutAlphaCounter;
	/** 頭にいれるインターバル */
	int m_interval;
	/** 評価値 */
	long m_rate;
}

/** 指定したファイルを連続再生するする */
class MoviePlayer {
	
	/** コンストラクタ */
	this() {
		movie = new MovieProxy();
		rand = new Rand();
		rand.randomize();
		m_intervalTimer = new Timer();
		m_timer = new Timer();
	}
	
	/** 動作 */
	void onMove(Screen screen) {
		try {
			if (playIndex >= m_playFilenames.length) {
				return;
			}
			
			if (!m_playing) {
				return;
			}
	
			auto currentMovieInfo = m_playFilenames[playIndex];
			if (m_intervalWait) {
				if (m_intervalTimer.get() >= currentMovieInfo.interval) {
					m_playing = false;
					m_intervalWait = false;
					next();
				}
			}
			else if (m_playing && !movie.isPlaying()) {
				
				// インターバルとるんか？
				if (!m_intervalWait && currentMovieInfo.interval > 0) {
					m_intervalWait = true;
					m_intervalTimer.reset();
					return;
				}
				
				m_playing = false;
				next();
			} else {
				currentMovieInfo.fadeinAlphaCounter.inc();
				if (!m_fadeout && currentMovieInfo.length - m_timer.get() < 1500) {
					m_fadeout = true;
				}
				if (m_fadeout) {
					currentMovieInfo.fadeoutAlphaCounter.inc();
				}
			}
		} catch {
			Log.printError("Movie movie error!");
			stop();
		}
	}
	
	/** 描画 */
	void onDraw(Screen screen) {
		if (!m_playing) {
			return;
		}

		if (playIndex >= m_playFilenames.length) {
			return;
		}

		auto currentMovieInfo = m_playFilenames[playIndex];
		auto texture = movie.getTexture();
		
		if (!currentMovieInfo.fadeinAlphaCounter.isEnd()) {
			screen.setColor(255,255,255,
					currentMovieInfo.fadeinAlphaCounter.get());
		} else if (m_fadeout) {
			screen.setColor(255,255,255,
					currentMovieInfo.fadeoutAlphaCounter.get());
		} else {
			screen.setColor(255,255,255,
					currentMovieInfo.baseAlpha + rand.get(currentMovieInfo.randAlpha));
		}

		screen.blendAddColorAlpha();
		screen.blt(texture, 0, 0);
	}
	
	/** プレイファイル名 */
	void setPlayFile(MovieFileInfo[] playFileNames) {
		m_playFilenames = playFileNames;
		playIndex = 0;
	}
	
	/** 再生 */
	void play() {
		// リストが設定されていない
		if (0 == m_playFilenames.length) {
			return;
		}
		// 全部終了
		if (playIndex >= m_playFilenames.length) {
			return;
		}
		movie.onLoad(m_playFilenames[playIndex].filename, false, 0.1f);
		movie.play();
		m_timer.reset();
		m_playing = true;
		m_fadeout = false;
	}
	
	/** 次へ */
	void next() {
		if (playIndex < m_playFilenames.length) {
			++playIndex;
			play();
		}
	}
	
	/** 停止 */
	void stop() {
		movie.stop();
	}
	
	/** 解放 */
	void release() {
		if (movie !is null) {
			try {
				movie.release();
			} catch {
				
			}
		}
		foreach(fileInfo; m_playFilenames) {
			fileInfo.release();
		}
	}
	
private:
	final Rand rand;
	final MovieProxy movie;
	final Timer m_intervalTimer;
	final Timer m_timer;
	bool m_intervalWait = false;
	bool m_playing;
	bool m_fadeout;
	MovieFileInfo[] m_playFilenames;
	int playIndex;
}