using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace pcd_g1
{
	class MainCharacterStageObject : CharacterStageObject
	{
		/*const*/
		private const double SPEED_ADD = 0.2;			//加速時速度変化率
		private const double SPEED_ADD_LAKE = 0.1;
		private const double SPEED_ADD_TURNING = 0.8;	//方向転換直後のスピード
		private const double SPEED_SUB = 0.5;			//減速時速度変化率
		private const double JUMP_POWER_ADDTIME = 10;	//ジャンプ時の上昇力変化の回数
		private const int JUMP_POWER_LEVEL1 = 12;		//level1でのjump power
		private const int DEFAULT_HP_MAX = 100;			//HPの初期値
		private const int SKILL_MAX_LEVEL1 = 50;		//level1でのレベルアップに必要なスキルの数値

		/*value*/
		private int zKeyPressedTime;		//Zキーが押されている時間
		private int weaponUsedTime;			//weaponが最後に使用された時のzKeyPressedTime
		private int weaponWaitTime = 20;	//weaponを連続して使用するときのwait
		private int damagedTime = 0;		//ダメージを受けた時の時間
		private bool dead = false;			//主人公が死んでいるかどうか
		int animationCount = 0;
		PEarthquakeEffect effect = new PEarthquakeEffect();

		/*save value*/
		public int character_number
		{
			get
			{
				if (StageManager.CurrentDataSet.GetInt("tail") > 0) return 31;
				if (StageManager.CurrentDataSet.GetInt("dodo") > 0) return 32;
				if (StageManager.CurrentDataSet.GetInt("babble") > 0) return 33;
				if (StageManager.CurrentDataSet.GetInt("tokagon") > 0) return 34;
				StageManager.CurrentDataSet.Set("tail", 1);
				return 31;
			}
			set
			{
				StageManager.CurrentDataSet.Set("tail", value == 31 ? 1 : 0);
				StageManager.CurrentDataSet.Set("dodo", value == 32 ? 1 : 0);
				StageManager.CurrentDataSet.Set("babble", value == 33 ? 1 : 0);
				StageManager.CurrentDataSet.Set("tokagon", value == 34 ? 1 : 0);
			}
		}	//画像番号nnd-xのうち、nnの部分

		private int jumpPower
		{
			get {
				if(level == 1) return JUMP_POWER_LEVEL1;
				if (level == 2) return (int)(JUMP_POWER_LEVEL1 * 1.2);
				if (level == 3) return (int)(JUMP_POWER_LEVEL1 * 1.5);
				return JUMP_POWER_LEVEL1;
			}
			
		}	//ジャンプ力

		int beforeCharacter = -1;
		public int hp
		{
			get { 
				var p = StageManager.CurrentDataSet.GetInt("MainCharacter" + character_number.ToString() + "HP");
				if (beforeCharacter != character_number)
				{
					beforeCharacter = character_number;
					if (p == 0)
					{
						StageManager.CurrentDataSet.Set("MainCharacter" + character_number.ToString() + "HP", max_hp);
						return max_hp;
					}
				}
				return p;
			}
			set { StageManager.CurrentDataSet.Set("MainCharacter" + character_number.ToString() + "HP", value); }
		}	//ヒットポイント

		public int max_hp
		{
			get 
			{
				if (level == 1) return 30;
				if (level == 2) return 50;
				if (level == 3) return 100;
				return 30;
			}
		}	//ヒットポイント最大値

		public int skill
		{
			get { return StageManager.CurrentDataSet.GetInt("MainCharacter" + character_number.ToString() + "Skill"); }
			set { StageManager.CurrentDataSet.Set("MainCharacter" + character_number.ToString() + "Skill", value); }
		}	//経験値

		public int nextLevelSkill
		{
			get 
			{
				if (level == 1) return 25;
				if (level == 2) return 50;
				return 999999999;
			}
		}	//LvUp経験値

		public int level
		{
			get { 
				int lv =  StageManager.CurrentDataSet.GetInt("MainCharacter" + character_number.ToString() + "Level");
				return lv>0 ? lv: 1; 
				}
			set { StageManager.CurrentDataSet.Set("MainCharacter" + character_number.ToString() + "Level", value); }
		}	//経験値

		private int moveSpeedMax
		{
			get 
			{
				return 8;	
			}
		}	//最大移動速度


		public MainCharacterStageObject(int x, int y, Stage stg) : base(x, y, stg)
		{
			//初期設定
			//重力の影響を受けないか
			isFloating = false;
			//初期状態の向いている方向
			moveDirection = direction.Right;

			Range = new FreeRectangleCollideRange(this);
			((FreeRectangleCollideRange)Range).Rect = new RectangleF(5f, 1f, 22f, 31f);

			//セーブデータに該当項目がない場合、初期値を各オプションに指定する。

			if (StageManager.CurrentDataSet.Contains("MainCharacter" + character_number.ToString() + "Level") == false)
			{
				level = 1;
			}

			if (StageManager.CurrentDataSet.Contains("MainCharacter" + character_number.ToString() + "HP") == false)
			{
				hp = max_hp;
			}
		}
		
		protected enum direction
		{
			Left = 2, Right = 1, Null = 0
		}
		protected direction moveDirection = direction.Null;

		private int jumpCount = -1;
		private bool jumpKeyPushed = true;
		//int soundCount = 0;
		public override void Update(int keyStatus, out int vx, out int vy)
		{
			base.Update(keyStatus, out vx, out vy);

			//左右移動
			if ((keyStatus & (int)MainForm.KEYBOARD.Left) != 0)
			{
				moveDirection = direction.Left;
				speedX -= speedX > 0 ? SPEED_ADD_TURNING : (owner.IsLake ? SPEED_ADD_LAKE : SPEED_ADD);
				//if(soundCount == 0)MainForm.PlayEffectSound("walk");
			}
			else if ((keyStatus & (int)MainForm.KEYBOARD.Right) != 0)
			{
				moveDirection = direction.Right;
				speedX += speedX < 0 ? SPEED_ADD_TURNING : (owner.IsLake ? SPEED_ADD_LAKE : SPEED_ADD);
				//if (soundCount == 0) MainForm.PlayEffectSound("walk");
			}
			else
			{
				//左右どちらも押されていないとき
				if (speedX > 0) if ((speedX -= SPEED_SUB) < 0) speedX = 0;
				if (speedX < 0) if ((speedX += SPEED_SUB) > 0) speedX = 0;
			}

			if (speedX > moveSpeedMax) speedX = moveSpeedMax;
			if (speedX < -moveSpeedMax) speedX = -moveSpeedMax;

			if ((keyStatus & (int)MainForm.KEYBOARD.X) != 0)
			{
				//接地しているか
				if (isSet && !jumpKeyPushed)
				{
					//ジャンプ時は、最初に半分の力を使用する。
					speedY = -(jumpPower >> 1);
					jumpCount = 0;
					jumpKeyPushed = true;
					MainForm.PlayEffectSound("jump");
				}
				else
				{
					if (jumpCount < JUMP_POWER_ADDTIME && jumpCount != -1)
					{
						//残り半分の力を時間差で加えてゆく。
						speedY -= (jumpPower >> 1) / JUMP_POWER_ADDTIME;
						jumpCount++;
					}
				}
			}
			else
			{
				jumpCount = -1;
				jumpKeyPushed = false;
			}

			vx = (int)speedX; vy = (int)speedY;
			owner.Command.ScrollStageCommand(this.X + (moveDirection == direction.Left ? -100 : 100), this.Y - 40);
			

			//武器の処理
			if ((keyStatus & (int)MainForm.KEYBOARD.Z) != 0){
				if (zKeyPressedTime - weaponUsedTime >= weaponWaitTime)
				{
					//レベル及びキャラクタ別分岐
					if (character_number == 31 || true)
					{
						WaveBombStageObject weapon;
						int x = X + ((moveDirection == direction.Left) ? -32 : 32);
						int y = Y;
						if (level == 1)
						{
							weapon = new WaveBombStageObject(x, y, owner, this, moveDirection == direction.Right, false, 2);
						}
						else if (level == 2)
						{
							weapon = new WaveBombStageObject(x, y, owner, this, moveDirection == direction.Right, false, 3);
						}
						else
						{
							weapon = new WaveBombStageObject(x, y, owner, this, moveDirection == direction.Right, true, 5);
						}
						BombStageObject.Go(weapon);
						MainForm.PlayEffectSound("shot");
					}
					weaponUsedTime = zKeyPressedTime;
				}
			}

			if ((keyStatus & (int)MainForm.KEYBOARD.Z) != 0){
				zKeyPressedTime++;
			} 
			else
			{
				zKeyPressedTime = 0;
				weaponUsedTime = -weaponWaitTime;
			}
		}

		public override void Draw(Graphics g, int width, int height)
		{
			if ((Environment.TickCount-damagedTime)<1000 && (Environment.TickCount - damagedTime) % 4 <2)
				return;

			string imageName;

			imageName = character_number.ToString();

			if (moveDirection == direction.Left)
			{
				imageName += "0-";
			}
			else
			{
				imageName += "1-";
			}

			if (speedX == 0)
			{
				imageName += "1";
			}
			else
			{
				imageName += (animationCount < 10 ? "1" : (animationCount < 20 ? "2" : (animationCount < 30 ? "1" : "3")));
			}
			animationCount++;
			if (animationCount >= 40) animationCount = 0;

			g.DrawImage(ImageManager.Search(imageName), 0, 0);
		}

		public override bool EventProc(EventType type, IStageObject sender, CollideDirection direction)
		{
			if (type == EventType.Collided)
			{
				if (direction == CollideDirection.Left || direction == CollideDirection.Right)
				{
					speedX = 0;
				}
			}
			return base.EventProc(type, sender, direction);
		}

		public override void SignalProc(SignalType type, int arg1, int arg2)
		{
			if (dead) return;

			switch (type) { 
				case SignalType.SIGDAMAGE:
					if (Environment.TickCount - damagedTime > 1000 || arg1>999)
					{
						hp -= arg1;
						damagedTime = Environment.TickCount;
						skill -= 1;
						if (skill < 0)
						{
							if (level == 1)
							{
								skill = 0;
							}
							else
							{
								level--;
								skill += nextLevelSkill;
								MainForm.PlayEffectSound("leveldn", true);
							}
						}
					}
					break;
				case SignalType.SIGUPSKILL:
					if (level < 3)
					{
						skill += arg1;
						if (skill >= nextLevelSkill)
						{
							skill -= nextLevelSkill;
							level++;
							hp = max_hp;
							MainForm.PlayEffectSound("levelup", true);
						}
					}
					break;
				case SignalType.SIGHEAL:
					hp += arg1;
					if (hp > max_hp) {
						hp = max_hp;
					}
					break;
			}

			//死亡時の処理
			if (hp <= 0 && dead == false)
			{
				dead = true;
				SelectStoryBoard selectStory;

				if (StageManager.CurrentDataSet.GetInt("lastfighting") == 0)
				{
					selectStory = new SelectStoryBoard("コンティニューしますか？", 400, 150, 230, 140, null, null, "はい", "いいえ");

					selectStory.OnStoryEnded += new StoryEndedEventHandler((IStoryboard storybord) =>
					{
						if (((SelectStoryBoard)storybord).Result == 0)
						{
							//死んだときにはHPを戻す
							hp = max_hp;
							StageManager.Continue();
						}
						else if (((SelectStoryBoard)storybord).Result == 1)
						{
							//メニューに戻る
							StageManager.RunStage(typeof(startMenuStage));
						}
					});
 
					owner.Command.MainCharacterDiedCommand();
					MainForm.PlaySound("");
					MainForm.PlayEffectSound("die");
					owner.Remove(this);
					Storyboard story = new Storyboard(new MessageStoryBoard("死 ん で し ま っ た ・ ・ ・ ・ 。\n"), selectStory);
					story.Run();
				}
				else
				{
					SelectStoryBoard selectStory2;
					Storyboard story;
					int new_character_number = 31;

					selectStory = new SelectStoryBoard("もう一度チャレンジしますか？", 400, 150, 230, 140, null, null, "チャレンジする", "コンティニューする");

					selectStory.OnStoryEnded += new StoryEndedEventHandler((IStoryboard storybord) =>
					{
						//死んだときにはHPを戻す
						hp = max_hp;
						if (((SelectStoryBoard)storybord).Result == 1)
						{
							StageManager.Continue();
						}
						else if (((SelectStoryBoard)storybord).Result == 0)
						{
							//もう一度ラスボス戦
							StageManager.RunStage("lastbattle7");
							StageManager.CurrentDataSet.Set("lfdead31", 0);
							StageManager.CurrentDataSet.Set("lfdead32", 0);
							StageManager.CurrentDataSet.Set("lfdead33", 0);
							StageManager.CurrentDataSet.Set("lfdead34", 0);
							StageManager.CurrentDataSet.Set("TaizanbokuHP", 40);
						}
					});

					owner.Command.MainCharacterDiedCommand();
					MainForm.PlaySound("");
					MainForm.PlayEffectSound("die");
					owner.Remove(this);
					StageManager.CurrentDataSet.Set("lfdead" + character_number.ToString(), 1);
					if (StageManager.CurrentDataSet.GetInt("lfdead31") == 0 ||
						StageManager.CurrentDataSet.GetInt("lfdead32") == 0 ||
						StageManager.CurrentDataSet.GetInt("lfdead33") == 0 ||
						StageManager.CurrentDataSet.GetInt("lfdead34") == 0)
					{
						selectStory2 = new SelectStoryBoard("も う だ め だ ・ ・ ・ 。\nあ と は 頼 ん だ ・ ・ ・\n", 400, 150, 230, 140, null, null, "次の仲間へ");
						selectStory2.OnStoryEnded += new StoryEndedEventHandler((IStoryboard storybord) =>
						{
							hp = max_hp;
							StageManager.RunStage("lastbattle7");
							character_number = new_character_number;
						});
						story = new Storyboard(selectStory2);
					}
					else
					{
						story = new Storyboard(new MessageStoryBoard("全 滅 し て し ま っ た ・ ・ ・ ・ 。\n"), selectStory);
					}


					if (StageManager.CurrentDataSet.GetInt("lfdead31") == 0)
					{
						new_character_number = 31;
					}
					else if (StageManager.CurrentDataSet.GetInt("lfdead32") == 0)
					{
						new_character_number = 32;
					}
					else if (StageManager.CurrentDataSet.GetInt("lfdead33") == 0)
					{
						new_character_number = 33;
					}
					else if (StageManager.CurrentDataSet.GetInt("lfdead34") == 0)
					{
						new_character_number = 34;
					}
					story.Run();
				}
			}

			base.SignalProc(type, arg1, arg2);
		}
	}
}