module kyojintati4d.component.ending.scenebase;

private import y4d;

private import kyojintati4d.gameinfo;
private import kyojintati4d.component.rhythm.keyconfigdialon;

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


class GamePointCal {
	
	static final float GREAT_POINT = 100;
	static final float GOOD_POINT = 50;
	static final float BAD_POINT = 25;
	static final float POOR_POINT = -25;
	static final float ERROR_POINT = -50;

	static final float GREAT_BONUS = 0.25f;
	static final float GOOD_BONUS = 0.10f;
	static final float BAD_BONUS = 0.0f;
	//static final float POOR_BONUS = 1.0f;
	//static final float ERROR_BONUS = 1.0f;

	/// ヒットステータスをカウントする
	float calcHitPoint(HitStatus status) {
		switch(status) {
		case HitStatus.GREAT:
			++m_greatCount;
			m_totalPoint += GREAT_POINT * m_bonusPoint;
			m_bonusPoint += GREAT_BONUS;
			break;
		case HitStatus.GOOD:
			++m_goodCount;
			m_totalPoint += GOOD_POINT * m_bonusPoint;
			m_bonusPoint += GOOD_BONUS;
			break;
		case HitStatus.BAD:
			++m_badCount;
			m_totalPoint += BAD_POINT * m_bonusPoint;
			m_bonusPoint += BAD_BONUS;
			break;
		case HitStatus.POOR:
			++m_poorCount;
			m_totalPoint += POOR_POINT;
			m_bonusPoint = 1.0f;
			break;
		case HitStatus.ERROR:
			++m_errorCount;
			m_totalPoint += ERROR_POINT;
			m_bonusPoint = 1.0f;
			break;
		default:
			return m_totalPoint;
		}
		
		m_statusHitory ~= status;
		
//		Log.print("POINT : %f, \t\tBONUS", m_totalPoint, m_bonusPoint);
		return m_totalPoint;
	}
	
	/** ステータスの履歴を返却する */
	HitStatus[] statusHistory() {
		return m_statusHitory;
	}
	
	int greatCount() {
		return m_greatCount;
	}
	
	int goodCount() {
		return m_goodCount;
	}
	
	int badCount() {
		return m_badCount;
	}
	
	int poorCount() {
		return m_poorCount;
	}
	
	int errorCount() {
		return m_errorCount;
	}
	
	float totalPoint() {
		return m_totalPoint;
	}
	
	float bonusPoint() {
		return m_bonusPoint;
	}
	
private:
	HitStatus[] m_statusHitory;
	int m_greatCount;
	int m_goodCount;
	int m_badCount;
	int m_poorCount;
	int m_errorCount;
	float m_totalPoint = 0.0f;
	float m_bonusPoint = 1.0f;
	
}

/**
 * エンディングシーンの共通変数・メソッドを定義
 */
public class EndingSceneBase {
public:
	static const long MUSIC_OFFSET_TIME = 4_500;

	static this() {
		gamePointCal = new GamePointCal();
	}
	
	static GamePointCal gamePointcalculator() {
		return gamePointCal;
	}

	TimingData[][] timingData() {
		return m_timingData;
	}
	
	bool isAutoHit() {
		return m_autoHit;
	}
	bool isAutoHit(bool value) {
		return m_autoHit = value;
	}
	
	void cacheTexture() {
		// キャッシュを実装してもＯＫ
	}
	
	// シーンは開始しているか
	bool isStart() {
		return true;
	}
	
	// シーンが終了したか
	bool isEnd() {
		return false;
	}
	
	// リソースの解放
	void release() {
	}
	
	abstract void onMove(Screen screen);
	abstract void onDraw(Screen screen);
	
protected:
	static void cacheTextureAll(TextureLoader loader) {
		for (int i = 0; i < loader.getInfoList().size(); ++i) {
			Texture t = loader.get(i);
		}
	}

	static bool isHitedStatus(HitStatus status) {
		//todo
		return HitStatus.POOR != status;
	}

	static class PhaseBase {
		/// コンストラクタ		
		this(TextObj obj, TextureLoader loader, HitStatus status) {
			m_start = true;
			m_textObj = obj.clone;
			m_textureLoader = loader;
			m_hitStatus = status;
		}
		
		abstract void onMove(Screen screen);
		abstract void onDraw(Screen screen);

		/// ヒットされたときにデフォルトの効果
		void onDrawHitText(Screen screen) {
		}
		
		bool start() {
			return m_start;
		}
		bool start(bool value) {
			return m_start = value;
		}
		
		bool end() {
			return m_end;
		}
		bool end(bool value) {
			return m_end = value;
		}
		
	protected:
		TextObj m_textObj;
		TextureLoader m_textureLoader;
		HitStatus m_hitStatus;

	private:
		RootCounterS m_hitTextAlpha;
		RootCounterS m_hitTextRate;
		bool m_start;
		bool m_end;
	}

	static void setScreenColorMax(Screen screen) {
		colorOrg = screen.getColor4ub();
		screen.setColor(255,255,255,255);
	}
	
	void repairColor(Screen screen) {
		screen.setColor(colorOrg);
	}
	
	/// ヒットステータスをカウントする
	void countHitStatus(HitStatus status) {
		switch(status) {
		case HitStatus.GREAT:
			++greatCount;
			break;
		case HitStatus.GOOD:
			++goodCount;
			break;
		case HitStatus.BAD:
			++badCount;
			break;
		case HitStatus.POOR:
			++poorCount;
			break;
		default:
			break;
		}
		gamePointCal.calcHitPoint(status);
	}
	
	/** タンポポ色 */
	static const Color4ub GREAT_COLOR = {r:251,g:236,b:53};
	/** ブルー */
	static const Color4ub GOOD_COLOR = {r:12,g:0,b:204};
	/** 灰白色 */
	static const Color4ub BAD_COLOR = {r:231,g:232,b:226};
	
	static HittingEffect createHitEffect(TextObj textObj) {
		switch(textObj.hitResult.hitStatus) {
		case HitStatus.GREAT:
			return new HittingEffect(textObj.img, textObj.pos.x, textObj.pos.y, textObj.alpha, 
					textObj.rate, textObj.rad, GREAT_COLOR);
			break;
		case HitStatus.GOOD:
			return new HittingEffect(textObj.img, textObj.pos.x, textObj.pos.y, textObj.alpha, 
					textObj.rate, textObj.rad, GOOD_COLOR);
			break;
		case HitStatus.BAD:
			return new HittingEffect(textObj.img, textObj.pos.x, textObj.pos.y, textObj.alpha, 
					textObj.rate, textObj.rad, GREAT_COLOR);
			break;
		case HitStatus.POOR:
			return null;
		default:
			return null;
		}
	}

	//---- 非公開フィールド＆メソッド
	static final GamePointCal gamePointCal;
	TimingData[][] m_timingData;
	int greatCount;
	int goodCount;
	int badCount;
	int poorCount;
	bool m_autoHit;
	
	static Color4ub colorOrg;
}

/** ヒットしたときの効果 */
public class HittingEffect {
	
	/** コンストラクタ */
	this(Texture tex, int x, int y, int startAlpha, float startRate, int rad, Color4ub color) {
		this.texture = tex;
		this.rateCounter = new RootCounterS(cast(int) (startRate * RATE_SCALE), 2560, RATE_SPEED);
		this.alphaCounter = new RootCounterS(startAlpha, 0, ALPHA_SPEED);
		this.posx = x;
		this.posy = y;
		this.rad = rad;
		this.drawColor = color;
	}
	
	/** 動作処理 */
	void onMove(Screen screen) {
		if (!drawEnd) {
			rateCounter.inc();
			alphaCounter.inc();
			drawEnd = alphaCounter.get() == 0;
		}
	}
	
	/** 描画処理 */
	void onDraw(Screen screen) {
		if (!drawEnd) {
			Color4ub colorOrg = screen.getColor4ub();
			screen.setColor(drawColor.r, drawColor.g, drawColor.b, alphaCounter.get());
			screen.bltRotate(texture, posx, posy, rad, rateCounter.get()/RATE_SCALE, 4);
			// カラー戻し
			screen.setColor(colorOrg);
		}
	}
	
	/** 終了したか */
	bool isEnd() {
		return drawEnd;
	}
	
private:
	/** 拡大率に使用しているスケール */
	static const float RATE_SCALE = 512.0f;
	/** 拡大スピード */
	static const int RATE_SPEED = 64;
	/** 消失スピード */
	static const int ALPHA_SPEED = 7;
	
	Texture texture;
	int posx;
	int posy;
	Color4ub drawColor;
	RootCounterS rateCounter;
	RootCounterS alphaCounter;
	int rad;
	bool drawEnd;
}
