using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;

namespace DebriefingSoftware.Common
{
	/// <summary>
	/// Parsing stuff
	/// </summary>
	public static class Parser
	{
		private static T? ParseNullable<T>(string s, ParseDelegate<T> parse) where T : struct
		{
			if (string.IsNullOrEmpty(s))
			{
				return null;
			}

			return parse(s);
		}

		public static int? ParseNullableInt(string s)
		{
			return ParseNullable(s, int.Parse);
		}

		public static short? ParseNullableShort(string s)
		{
			return ParseNullable(s, short.Parse);
		}

		public static float? ParseNullableFloat(string s)
		{
			return ParseNullable(s, float.Parse);
		}

		public static DateTime? ParseNullableDateTime(string s)
		{
			return ParseNullable(s, DateTime.Parse);
		}

		public static bool? ParseNullableBool(string s)
		{
			return ParseNullable(s, bool.Parse);
		}

		public static string ShortDateTime(DateTime? dt)
		{
			if (dt.HasValue)
			{
				return ((DateTime)dt).ToShortDateString();
			}

			return String.Empty;
		}

		public static string GenerateAlphaNumericWord(int length, char? upperlower)
		{
			var random = new Random();
			var result = String.Empty;

			if (upperlower.HasValue && upperlower != 'u')
			{
				upperlower = 'l';
			}

			if (length > 0)
			{
				if (length > 256)
				{
					result = "crazy";
				}
				else
				{
					var word = new Char[length];
					for (var i = 0; i < word.Length; i++)
					{
						word[i] = random.NextDouble() > 0.5
									? upperlower.HasValue
										? (upperlower == 'u' ? Convert.ToChar(random.Next(65, 91)) : Convert.ToChar(random.Next(97, 122)))
										: random.NextDouble() > 0.75
											? Convert.ToChar(random.Next(97, 122))
											: Convert.ToChar(random.Next(65, 91))
									: Convert.ToChar(48 + random.Next(0, 10));
					}
					result = new string(word);
				}
			}

			return result;
		}

		public static string GenerateAlphaNumericWord(string mask, char? upperlower)
		{
			var result = String.Empty;
			var maskArray = mask.ToCharArray();

			if (upperlower.HasValue && upperlower != 'u')
			{
				upperlower = 'l';
			}

			if (maskArray.Length > 0)
			{
				var random = new Random();
				for (var i = 0; i < maskArray.Length; i++)
				{
					switch (mask[i])
					{
						case '#':
							maskArray[i] = Convert.ToChar(48 + random.Next(0, 10));
							break;
						case '%':
							maskArray[i] = upperlower.HasValue
								? (upperlower == 'u' ? Convert.ToChar(random.Next(65, 91)) : Convert.ToChar(random.Next(97, 122)))
								: random.NextDouble() > 0.5
									? Convert.ToChar(random.Next(97, 122))
									: Convert.ToChar(random.Next(65, 91));
							break;
						case '$':
							maskArray[i] = random.NextDouble() > 0.5
								? upperlower.HasValue ? (upperlower == 'u' ? Convert.ToChar(random.Next(65, 91)) : Convert.ToChar(random.Next(97, 122)))
														: random.NextDouble() > 0.75 ? Convert.ToChar(random.Next(97, 122)) : Convert.ToChar(random.Next(65, 91))
								: Convert.ToChar(48 + random.Next(0, 10));
							break;
					}
				}
				result = new String(maskArray);
			}

			return result;
		}

		public static IEnumerable<string> Split(string str, int chunkSize)
		{
			var result = Enumerable.Range(0, str.Length / chunkSize + 1).Select(i => str.Substring(i * chunkSize, (i + 1) * chunkSize > str.Length ? str.Length - i * chunkSize : chunkSize));

			return result;
		}

		public static string SplitIgnoreSpaces(string str, int chunkSize)
		{
			var stringChunks = Split(str, 140).ToArray();
			var result = new StringBuilder();

			for (var i = 0; i < stringChunks.Length; i++)
			{
				if (stringChunks[i].TrimEnd(' ').IndexOf(' ') != -1)
				{
					result.Append(stringChunks[i]);
				}
				else
				{
					if (i > 0)
					{
						result.AppendFormat(" {0}", stringChunks[i]);
					}
				}
			}

			return result.ToString();
		}

		#region Nested type: ParseDelegate

		/// <summary>
		/// Parse different types.
		/// </summary>
		private delegate T ParseDelegate<out T>(string s);

		#endregion
	}
}