using System;
using System.Collections.Generic;
using System.IO;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;


namespace PickupTheCrew
{
	public class Shark: Sprite
	{
		public static float StartMovementSpeed = (float)0.04;
		public static float MovementSpeed = StartMovementSpeed;
		public static float MovementSpeedIncrement = (float)0.03;
		float detectionDistance = 175;

		/// <summary>
		/// Makes a new shark.
		/// </summary>
		/// <param name="inPosition">The starting position.</param>
		public Shark(Vector2 inPosition) : base(PickupTheCrew.textures["shark"], inPosition)
		{
			Size.X = Size.Y = 32;
		}

		/// <summary>
		/// Updates the shark ready for the next frame.
		/// </summary>
		/// <param name="gameTime">The time that has passed since the last frame was drawn.</param>
		/// <param name="game">A reference to the game that this shark is part of.</param>
		public override void Update(GameTime gameTime, PickupTheCrew game)
		{
			Vector2 target = game.PlayerObject.Position;

			// vector distance to target
			Vector2 diff = Utilities.CalculateDistanceDifference(Position, target);

			// distance to target as a number
			double length = Math.Sqrt((diff.X * diff.X) + (diff.Y * diff.Y));

			// update the speed
			if(length < detectionDistance && length > 2) // todo make sure that we don't collide with any other sharks
			{
				Speed = new Vector2(
					(float)((diff.X / length) * MovementSpeed),
					(float)((diff.Y / length) * MovementSpeed)
				);
			}
			else
			{
				Speed = Vector2.Zero;
			}

			base.Update(gameTime, game);
		}

		/// <summary>
		/// Draws the shark to the screen.
		/// </summary>
		/// <param name="gameTime">The time that has passed since the last frame was drawn.</param>
		/// <param name="spriteBatch">The SpriteBatch to use for drawing.</param>
		public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
		{
#if DEBUG
			Utilities.DrawRectangle(spriteBatch, DrawArea, Color.DarkGray, 2);

			Rectangle detectionBox = new Rectangle();
			detectionBox.X = (int)(Position.X - (detectionDistance / 2));
			detectionBox.Y = (int)(Position.Y - (detectionDistance / 2));
			detectionBox.Width = detectionBox.Height = (int)detectionDistance;
			Utilities.DrawRectangle(spriteBatch, detectionBox, Color.SlateGray, 2);
#endif

			base.Draw(gameTime, spriteBatch);
		}

		/// <summary>
		/// Resets the shark.
		/// </summary>
		/// <param name="game">A reference to the game that this shark is part of.</param>
		public override void Reset(PickupTheCrew game)
		{
			base.Reset(game);

			// Reset our speed
			MovementSpeed = StartMovementSpeed;

			// Reposition ourselves, but make sure we aren't too close to the player
			do
			{
				Position.X = game.randGenerator.Next((int)Size.X, (int)(game.GraphicsDevice.Viewport.Width - Size.X));
				Position.Y = game.randGenerator.Next((int)Size.Y, (int)(game.GraphicsDevice.Viewport.Height - Size.Y));
			} while (Utilities.CalculateDistance(Position, game.PlayerObject.Position) < detectionDistance);

			// Update the DrawArea since the main update method isn't called during the LevelUp state
			UpdateDrawArea();
		}

		/// <summary>
		/// Saves the shark's state information (position etc.) to a given StreamWriter.
		/// </summary>
		/// <param name="destination">The StreamWriter to output the state information to.</param>
		public override void Save(StreamWriter destination)
		{
			base.Save(destination);

			destination.WriteLine("movementSpeed:{0}|detectionDistance:{1}", MovementSpeed, detectionDistance);
		}

		/// <summary>
		/// Special constructor that loads a shark from a given StreamReader.
		/// </summary>
		/// <param name="source">The StreamReader we should load the shark from.</param>
		public Shark(StreamReader source) : base(source)
		{
			Dictionary<string, string> saveData = Utilities.DecodeSaveString(source.ReadLine());

			MovementSpeed = float.Parse(saveData["movementSpeed"]);
			detectionDistance = float.Parse(saveData["detectionDistance"]);
		}
	}
}
