using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using ShootingHero.Components;
using Microsoft.Xna.Framework.Graphics;
using ShootingHero.Components.Monsters;
using ShootingHero.Components.Manager;
using ShootingHero.Utilities;
using ShootingHero.Components.Monsters.Bosses;
using ShootingHero.Components.Backgrounds;
using System.Diagnostics;
using Microsoft.Xna.Framework.Input;
#if ANDROID || IOS
using Microsoft.Xna.Framework.Input.Touch;
#endif

namespace ShootingHero.Scene
{
	public class GameScene : DrawableGameComponent
	{
		Background background;
		Player player;
		Stage stage;
		float moveUnit;

		BulletManager bulletManager;
		MonsterManager monsterManager;
		EffectManager effectManager;
		ItemManager itemManager;

		Texture2D uiFrame, changePointGage, blingblingCPGage, healthPointGage, bombIcon;
		Texture2D clearMessage, gameOverMessage, startMessage, stageMessage, readyMessage;
		Texture2D subMenuFan, subMenuPause, subMenuReturn, subMenuExit;
		Font drawingFont;

		Timer blingblingTimer;
		bool blingblingState = true, pauseBling = true;

		Timer modeTimer;
		bool isBeginMode = true, isReadyMode = false, isStartMode = false, isGameOverMode = false, isClearMode = false, isSubMenuMode = false;

		bool releaseMode = false;

		Type [] minionType = { null, typeof ( Chick ), typeof ( Squirrel ), typeof ( Fish ), typeof ( Spider ),
										 typeof ( Lizard ), typeof ( Ufo ) };
		Type [] bossType = { null, typeof ( Chicken ), typeof ( HugeSquirrel ), typeof ( Shark ), typeof ( HugeSpider ),
									   typeof ( Komodo ), typeof ( HugeUfo ) };
		
		public float MoveUnit { get { return moveUnit; } }
		
		public BulletManager BulletManager { get { return bulletManager; } }
		public MonsterManager MonsterManager { get { return monsterManager; } }
		public EffectManager EffectManager { get { return effectManager; } }
		public ItemManager ItemManager { get { return itemManager; } }

		public Player Player { get { return player; } }

		public GameScene ( Game game, Stage stage, Player player )
			: base ( game )
		{
			this.player = player;
			this.stage = stage;
			blingblingTimer = new Timer ( 500 );
			modeTimer = new Timer ( 1000 );
		}

		public override void Initialize ()
		{
			bulletManager = new BulletManager ( Game );
			monsterManager = new MonsterManager ( Game );
			effectManager = new EffectManager ( Game );
			itemManager = new ItemManager ( Game );

			base.Initialize ();
		}

		protected override void LoadContent ()
		{
			player.Initialize ();
			
			background = new Background ( Game, stage );
			background.Initialize ();

			uiFrame = Game.Content.Load<Texture2D> ( "UI/ui_test" );
			healthPointGage = Game.Content.Load<Texture2D> ( "UI/hp" );
			changePointGage = Game.Content.Load<Texture2D> ( "UI/changebar" );
			blingblingCPGage = Game.Content.Load<Texture2D> ( "UI/change" );
			bombIcon = Game.Content.Load<Texture2D> ( "UI/ui_boom" );

			subMenuFan = Game.Content.Load<Texture2D> ( "Menu/Popup/popup_popup" );
			subMenuPause = Game.Content.Load<Texture2D> ( "Menu/Popup/popup_pause" );
			subMenuReturn = Game.Content.Load<Texture2D> ( "Menu/Popup/popup_return" );
			subMenuExit = Game.Content.Load<Texture2D> ( "Menu/Popup/popup_exit" );

			drawingFont = new Font ( Game.Content.Load<Texture2D> ( "Font/font" ) );

			clearMessage = Game.Content.Load<Texture2D> ( "Messages/clear" );
			readyMessage = Game.Content.Load<Texture2D> ( "Messages/ready" );
			startMessage = Game.Content.Load<Texture2D> ( "Messages/start" );
			gameOverMessage = Game.Content.Load<Texture2D> ( "Messages/gameover" );
			if ( stage != Stage.InfinityStage )
				stageMessage = Game.Content.Load<Texture2D> ( "Messages/stage" + ( int ) stage );
			else { isBeginMode = false; isReadyMode = true; }

			string stageData = "";
			switch ( stage )
			{
				case Stage.Stage1:
				case Stage.Stage2:
				case Stage.Stage3:
				case Stage.Stage4:
				case Stage.Stage5:
				case Stage.Stage6:
					byte [] data = Game.Content.Load<byte []> ( "Stage/Stage" + ( ( int ) stage ).ToString () );
					stageData = Encoding.UTF8.GetString ( data, 0, data.Length );
					break;
			}

			if ( stageData != "" )
			{
				string [] monsters = stageData.Split ( '\n' );
				foreach ( string monster in monsters )
				{
					string [] data = monster.Replace ( "\r", "" ).Split ( ' ' );
					if ( data [ 0 ] == "m" )
					{
						monsterManager.Add ( Activator.CreateInstance ( minionType [ int.Parse ( data [ 1 ] ) ], Game,
							( float ) int.Parse ( data [ 2 ] ), float.Parse ( data [ 3 ] ), ( float ) int.Parse ( data [ 4 ] ) ) as Monster );
					}
					else
					{
						monsterManager.Add ( Activator.CreateInstance ( bossType [ int.Parse ( data [ 1 ] ) ],
							Game, ( float ) int.Parse ( data [ 2 ] ) ) as Boss );
					}
				}
			}

			base.LoadContent ();
		}

		public override void Update ( GameTime gameTime )
		{
			if ( !isBeginMode && !isClearMode && !isStartMode && !isGameOverMode && !isReadyMode && !isSubMenuMode )
			{
				KeyboardState keyboard = Keyboard.GetState ();
				GamePadState gamePad = GamePad.GetState ( PlayerIndex.One );

				IEnumerable<Monster> bosses = from monster in monsterManager.Container
											  where ( monster is Boss ) && !monster.CheckTimeUnit
											  select monster;
				if ( bosses.Count () == 0 )
					moveUnit += gameTime.ElapsedGameTime.Milliseconds;

				if ( stage == Stage.InfinityStage )
				{
					float lastMoveUnit = ( monsterManager.Container.Count == 0 ) ? moveUnit :
						monsterManager.Container [ monsterManager.Container.Count - 1 ].MoveUnit;
					for ( int i = monsterManager.Container.Count; i <= 10; i++ )
					{
						Random random = ( Game as ShootingHero ).Random;
						switch ( random.Next ( 0, 50 ) )
						{
							case 15:
								MonsterManager.Add ( Activator.CreateInstance ( bossType [ random.Next ( 1, 7 ) ],
									Game, lastMoveUnit += 500 ) as Monster );
								break;
							default:
								MonsterManager.Add ( Activator.CreateInstance ( minionType [ random.Next ( 1, 7 ) ],
									Game, random.Next ( 0, 480 ),
									Microsoft.Xna.Framework.MathHelper.ToRadians ( random.Next ( 120, 240 ) ),
									lastMoveUnit += 500 ) as Monster );
								break;
						}
					}
				}

				background.Update ( gameTime );
				player.Update ( gameTime );

				bulletManager.Update ( gameTime );
				monsterManager.Update ( gameTime );
				effectManager.Update ( gameTime );
				itemManager.Update ( gameTime );

				if ( gamePad.Buttons.Back == ButtonState.Pressed ||
					keyboard.IsKeyDown ( Keys.Escape ) )
				{
					if ( !releaseMode )
					{
						isSubMenuMode = true;
						releaseMode = true;
					}
				}
				else releaseMode = false;

#if ANDROID || IOS
				TouchCollection touches = TouchPanel.GetState ();
				if( touches.Count > 0 && touches[0].State == TouchLocationState.Pressed )
				{
					int x = ( int ) touches [ 0 ].Position.X,
						y = ( int ) touches [ 0 ].Position.Y;
#else
				MouseState mouse = Mouse.GetState ();
				if ( mouse.LeftButton == ButtonState.Pressed )
				{
					int x = mouse.X, y = mouse.Y;
#endif
					if ( x <= 474 && 312 <= x && y <= 794 && 724 <= y )
						isSubMenuMode = true;
				}

				if ( player.HealthPoint <= 0 )
					isGameOverMode = true;

				if ( stage != Stage.InfinityStage && monsterManager.Container.Count <= 0 )
					isClearMode = true;
			}
			else
			{
				if ( isSubMenuMode )
				{
					blingblingTimer.Update ( gameTime );
					if ( blingblingTimer.CheckTimer )
					{
						pauseBling = !pauseBling;
						blingblingTimer.Reset ();
					}

#if ANDROID || IOS
					TouchCollection touches = TouchPanel.GetState ();
					if ( touches.Count > 0 && touches [ 0 ].State == TouchLocationState.Pressed )
					{
						int x = ( int ) touches [ 0 ].Position.X,
							y = ( int ) touches [ 0 ].Position.Y;
#else
					MouseState mouse = Mouse.GetState ();
					if ( mouse.LeftButton == ButtonState.Pressed )
					{
						int x = mouse.X, y = mouse.Y;
#endif
						if ( x <= 177 + 165 && 177 <= x && y <= 380 + 45 && 380 <= y )
							isSubMenuMode = false;
						if ( x <= 177 + 165 && 177 <= x && y <= 500 + 45 && 500 <= y )
							( Game.Components [ 0 ] as Transitor ).Transition ( new MenuScene ( Game ) );
					}

					if ( GamePad.GetState ( PlayerIndex.One ).Buttons.Back == ButtonState.Pressed ||
						Keyboard.GetState ().IsKeyDown ( Keys.Escape ) )
					{
						if ( !releaseMode )
						{
							isSubMenuMode = false;
							releaseMode = true;
						}
					}
					else releaseMode = false;
				}
				else
				{
					modeTimer.Update ( gameTime );
					if ( modeTimer.CheckTimer )
					{
						if ( isBeginMode ) { isBeginMode = false; isReadyMode = true; }
						else if ( isReadyMode ) { isReadyMode = false; isStartMode = true; }
						else if ( isStartMode ) { isStartMode = false; }
						else if ( isClearMode )
						{
							if ( stage <= Stage.Stage5 )
								( Game.Components [ 0 ] as Transitor ).Transition ( new GameScene ( Game, ++stage, player ) );
							else
								( Game.Components [ 0 ] as Transitor ).Transition ( new RankingScene ( Game, ( int ) stage, player.Score ) );
						}
						else if ( isGameOverMode )
							( Game.Components [ 0 ] as Transitor ).Transition ( new RankingScene ( Game, ( int ) stage, player.Score ) );
						modeTimer.FullReset ();
					}
				}
			}

			base.Update ( gameTime );
		}

		public override void Draw ( GameTime gameTime )
		{
			SpriteBatch spriteBatch = ( Game as ShootingHero ).SpriteBatch;

			/* =========================================================================================
			 * Drawing Background
			 ======================================================================================== */
			background.Draw ( gameTime );

			/* =========================================================================================
			 * Drawing Game Objects
			 ======================================================================================== */
			player.Draw ( gameTime );
			bulletManager.Draw ( gameTime );
			monsterManager.Draw ( gameTime );
			itemManager.Draw ( gameTime );
			effectManager.Draw ( gameTime );

			/* =========================================================================================
			 * Drawing UI Frame
			 ======================================================================================== */
			spriteBatch.Draw ( uiFrame, new Vector2 (), Color.White );

			/* =========================================================================================
			 * Drawing Player Health Point Gage
			 ======================================================================================== */
			if ( player.HealthPoint < 20 )
				spriteBatch.Draw ( healthPointGage, new Vector2 ( 12, 12 ),
					new Rectangle ( 0, 0, ( int ) ( ( player.HealthPoint % 20 ) / 20.0f * healthPointGage.Width ), healthPointGage.Height ),
					Color.White );
			else if ( player.HealthPoint >= 20 ) spriteBatch.Draw ( healthPointGage, new Vector2 ( 12, 12 ), Color.White );

			if ( player.HealthPoint > 20 && player.HealthPoint < 40 )
				spriteBatch.Draw ( healthPointGage, new Vector2 ( 96, 12 ),
					new Rectangle ( 0, 0, ( int ) ( ( player.HealthPoint % 20 ) / 20.0f * healthPointGage.Width ), healthPointGage.Height ),
					Color.White );
			else if(player.HealthPoint >= 40) spriteBatch.Draw ( healthPointGage, new Vector2 ( 96, 12 ), Color.White );

			if ( player.HealthPoint > 40 && player.HealthPoint < 60 )
				spriteBatch.Draw ( healthPointGage, new Vector2 ( 178, 12 ),
					new Rectangle ( 0, 0, ( int ) ( ( player.HealthPoint % 20 ) / 20.0f * healthPointGage.Width ), healthPointGage.Height ),
					Color.White );
			else if(player.HealthPoint >= 60) spriteBatch.Draw ( healthPointGage, new Vector2 ( 178, 12 ), Color.White );
			
			/* =========================================================================================
			 * Drawing Player Change Point Gage
			 ======================================================================================== */
			if ( !player.IsSuperMode && player.ChangePoint == 100 )
			{
				blingblingTimer.Update ( gameTime );
				if ( blingblingTimer.CheckTimer )
				{
					blingblingState = !blingblingState;
					blingblingTimer.Reset ();
				}
			}
			else
				blingblingState = false;

			spriteBatch.Draw ( changePointGage, new Vector2 ( 12, 762 ),
				new Rectangle ( 0, 0, ( int ) ( player.ChangePoint / 100.0f * changePointGage.Width ), changePointGage.Height ),
				Color.White );
			if ( blingblingState )
				spriteBatch.Draw ( blingblingCPGage, new Vector2 ( 12 - 7, 762 - 7 ), Color.White );

			/* =========================================================================================
			 * Drawing Player Bomber having state
			 ======================================================================================== */
			if ( player.Bomber/* || player.IsSuperMode*/ )
				spriteBatch.Draw ( bombIcon, new Vector2 ( 380, 18 ), Color.White );

			/* =========================================================================================
			 * Drawing Player Score and Level
			 ======================================================================================== */
			drawingFont.DrawFont ( spriteBatch, player.Score, 300, 760, Color.White, true );
			drawingFont.DrawFont ( spriteBatch, player.Level, 454, 722, Color.White, false );

			/* =========================================================================================
			 * Drawing Sub Menu
			 ======================================================================================== */
			if ( isSubMenuMode )
			{
				spriteBatch.Draw ( subMenuFan,
					new Vector2 ( 0, 800 / 2 - subMenuFan.Height / 2 ),
					Color.White );
				if ( pauseBling )
					spriteBatch.Draw ( subMenuPause,
						new Vector2 ( 480 / 2 - subMenuPause.Width / 2 + 20, 290 ),
						Color.White );
				spriteBatch.Draw ( subMenuReturn,
					new Vector2 ( 480 / 2 - subMenuReturn.Width / 2 + 20, 380 ),
					Color.White );
				spriteBatch.Draw ( subMenuExit,
					new Vector2 ( 480 / 2 - subMenuExit.Width / 2 + 20, 500 ),
					Color.White );
			}

			/* =========================================================================================
			 * Drawing Messages
			 ======================================================================================== */
			if ( isBeginMode )
				spriteBatch.Draw ( stageMessage,
					new Vector2 ( 480 / 2 - stageMessage.Width / 2, 800 / 2 - stageMessage.Height / 2 ),
					Color.White );
			if ( isReadyMode )
				spriteBatch.Draw ( readyMessage,
					new Vector2 ( 480 / 2 - readyMessage.Width / 2, 800 / 2 - readyMessage.Height / 2 ),
					Color.White );
			if ( isStartMode )
				spriteBatch.Draw ( startMessage,
					new Vector2 ( 480 / 2 - startMessage.Width / 2, 800 / 2 - startMessage.Height / 2 ),
					Color.White );
			if ( isClearMode )
				spriteBatch.Draw ( clearMessage,
					new Vector2 ( 480 / 2 - clearMessage.Width / 2, 800 / 2 - clearMessage.Height / 2 ),
					Color.White );
			if ( isGameOverMode )
				spriteBatch.Draw ( gameOverMessage,
					new Vector2 ( 480 / 2 - gameOverMessage.Width / 2, 800 / 2 - gameOverMessage.Height / 2 ),
					Color.White );

			base.Draw ( gameTime );
		}
	}
}
