using System;
using System.Collections.Generic;

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

namespace PickupTheCrew
{
	class Utilities
	{
		static Random rand = new Random();
		static char[] idCharPool = "abcdefghijklmnopqrstuvwxyz0123456789".ToCharArray();

		/// <summary>
		/// Generates a new random ID. Useful for recording who is following who. Note that this is NOT cryptographically secure.
		/// </summary>
		/// <returns>The newly generated random ID.</returns>
		public static string GetRandomId()
		{
			string newID = "";
			for (int i = 0; i < 16; i++)
			{
				newID += idCharPool[rand.Next(idCharPool.Length)];
			}

			return newID;
		}

		/// <summary>
		/// Decodes a save string into a dictionary.
		/// </summary>
		/// <param name="saveString">The string to decode.</param>
		/// <returns>The deocded string as a dictionary.</returns>
		public static Dictionary<string, string> DecodeSaveString(string saveString)
		{
			Dictionary<string, string> result = new Dictionary<string, string>();
			string[] parts = saveString.Split('|');
			foreach(string part in parts)
			{
				if (part[0] == '*') continue; // lines that start with an asterick are comments
				string[] entry = part.Split(':');
				if (entry.Length != 2)
					throw new FormatException(String.Format("Invalid save file entry '{0}'. entry length: {1}.", part, entry.Length));
				result.Add(entry[0], entry[1]);
			}

			return result;
		}

		/// <summary>
		/// Converts strings like 'CommanderCustard' to 'Commander Custard'.
		/// </summary>
		/// <param name="inString">The string to process.</param>
		/// <returns>The processed string.</returns>
		public static string CamelCaseToReadable(string inString)
		{
			for (int i = 0; i < inString.Length; i++)
			{
				if(char.IsUpper(inString[i]))
				{
					inString = inString.Insert(i, " ");
					i += 2; // skip over both the space and the upper case character
				}
			}
			return inString;
		}

		/// <summary>
		/// Calculates the distance between two points.
		/// </summary>
		/// <param name="from">The first point.</param>
		/// <param name="to">The second point.</param>
		/// <returns>The distance between them.</returns>
		public static float CalculateDistance(Vector2 from, Vector2 to)
		{
			Vector2 vectorDistance = Vector2.Subtract(to, from);
			return (float)Math.Sqrt((vectorDistance.X * vectorDistance.X) + (vectorDistance.Y * vectorDistance.Y));
		}

		/// <summary>
		/// Calculates the difference between two Vectors.
		/// </summary>
		/// <param name="from">The starting vector</param>
		/// <param name="from">The ending vector</param>
		/// <returns></returns>
		public static Vector2 CalculateDistanceDifference(Vector2 from, Vector2 to)
		{
			Vector2 diff = new Vector2(to.X - from.X, to.Y - from.Y); //used to be from - target
			return diff;
		}

		/// <summary>
		/// Draws a string centred on a postion.
		/// </summary>
		/// <param name="spriteBatch">The spriteBatch to use when drawing.</param>
		/// <param name="font">The font to use to draw the text</param>
		/// <param name="text">The string to draw</param>
		/// <param name="position">The position to draw the text</param>
		/// <param name="textColour">The colour to use when drawing.</param>
		public static void DrawStringCentred(SpriteBatch spriteBatch, SpriteFont font, string text, Vector2 position, Color textColour)
		{
			Vector2 size = font.MeasureString(text);
			position.X -= size.X / 2;
			position.Y -= size.Y / 2;
			spriteBatch.DrawString(font, text, position, textColour);
		}

#if DEBUG
		// From http://stackoverflow.com/a/13894313/1460422
		// for debugging purposes only
		static Texture2D _pointTexture;
		public static void DrawRectangle(SpriteBatch spriteBatch, Rectangle rectangle, Color color, int lineWidth)
		{
			if (_pointTexture == null)
			{
				_pointTexture = new Texture2D(spriteBatch.GraphicsDevice, 1, 1);
				_pointTexture.SetData<Color>(new Color[] { Color.White });
			}

			spriteBatch.Draw(_pointTexture, new Rectangle(rectangle.X, rectangle.Y, lineWidth, rectangle.Height + lineWidth), color);
			spriteBatch.Draw(_pointTexture, new Rectangle(rectangle.X, rectangle.Y, rectangle.Width + lineWidth, lineWidth), color);
			spriteBatch.Draw(_pointTexture, new Rectangle(rectangle.X + rectangle.Width, rectangle.Y, lineWidth, rectangle.Height + lineWidth), color);
			spriteBatch.Draw(_pointTexture, new Rectangle(rectangle.X, rectangle.Y + rectangle.Height, rectangle.Width + lineWidth, lineWidth), color);
		}
#endif
	}
}
