using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using CaLib.User;
using System.Globalization;

namespace ClipClop.User
{
	public abstract class ContextMenuSettingHelper
	{
		static readonly CultureInfo jpCulture_;
		static readonly CultureInfo enCulture_;

		static ContextMenuSettingHelper()
		{
			jpCulture_ = new CultureInfo("ja-JP");
			jpCulture_.DateTimeFormat.Calendar = new System.Globalization.JapaneseCalendar();

			enCulture_ = new CultureInfo("en-US");
		}

		public static XmlNode GetRoot(XmlDocument doc)
		{
			if (doc == null)
				return null;

			foreach (XmlNode node in doc.ChildNodes)
			{
				if (node.Name == ContextMenuSettingDefinition.Root_)
					return node;
			}
			return null;
		}

		public static string GetAttributeValue(XmlNode node, string name)
		{
			XmlAttribute attri = node.Attributes[name];
			if (null != attri)
				return attri.Value;
			return null;
		}

		public static bool IsRoot(XmlNode root)
		{
			if (string.IsNullOrEmpty(GetAttributeValue(root, ContextMenuSettingDefinition.RootAttribute.magicnumber.ToString()))
				|| string.IsNullOrEmpty(GetAttributeValue(root, ContextMenuSettingDefinition.RootAttribute.version.ToString())))
			{
				return false;
			}

			return true;
		}

		public static void CheckAsRoot(XmlNode root)
		{
			if (!IsRoot(root))
			{
				throw new FundamentalException(global::ClipClop.Properties.Resources.EF006);
			}

			if (root.Attributes[ContextMenuSettingDefinition.RootAttribute.magicnumber.ToString()].Value != ContextMenuSettingDefinition.MagicNumber)
			{
				throw new FundamentalException(global::ClipClop.Properties.Resources.EF006);
			}

			int ver = Convert.ToInt32(root.Attributes[ContextMenuSettingDefinition.RootAttribute.version.ToString()].Value, 16);
			if (ver > ContextMenuSettingDefinition.CurrnetVersion)
			{
				throw new FundamentalException(global::ClipClop.Properties.Resources.EF007);
			}
		}

		public static string GetDisplayString(XmlNode node)
		{
			if (ContextMenuSettingDefinition.Sentence_ == node.Name ||
				ContextMenuSettingDefinition.Folder_ == node.Name)
			{
				XmlAttribute attri = node.Attributes[ContextMenuSettingDefinition.Name_];
				if (attri == null)
				{
					//Nameがなければ
					attri = node.Attributes[ContextMenuSettingDefinition.Value_];
				}

				return attri.Value;
			}
			return node.Name;
		}

		public static bool SetNameAttribute(XmlNode node, string str, XmlDocument doc)
		{
			if (ContextMenuSettingDefinition.Sentence_ == node.Name ||
				ContextMenuSettingDefinition.Folder_ == node.Name)
			{
				XmlAttribute attri = node.Attributes[ContextMenuSettingDefinition.Name_];
				if (attri == null)
				{
					attri = doc.CreateAttribute(ContextMenuSettingDefinition.Name_);
					node.Attributes.Append(attri);
				}

				attri.Value = str;
				return true;
			}
			return false;
		}


		public static string GetValue(XmlNode node)
		{
			if (ContextMenuSettingDefinition.Sentence_ == node.Name )
			{
				XmlAttribute attri = node.Attributes[ContextMenuSettingDefinition.Value_];
				if( null!= attri )
					return attri.Value;
			}
			return string.Empty;
		}

		public static bool SetValueAttribute(XmlNode node, string str, XmlDocument doc)
		{
			if (ContextMenuSettingDefinition.Sentence_ == node.Name)
			{
				XmlAttribute attri = node.Attributes[ContextMenuSettingDefinition.Value_];
				if (null == attri)
				{
					attri = doc.CreateAttribute(ContextMenuSettingDefinition.Value_);
					node.Attributes.Append(attri);					
				}
				attri.Value = str;
				return true;
			}
			return false;
		}

		public class Pair
		{
			readonly string key_;
			readonly string value_;
			
			public Pair(string key, string value)
			{
				key_ = key;
				value_ = value;
			}

			public string Key
			{
				get
				{
					return this.key_;
				}
			}
			public string Value
			{
				get
				{
					return this.value_;
				}
			}
		}

		public static readonly Pair[] ExeNames = { 
													new Pair("EXPLORER","explorer.exe"),
													new Pair("NOTEPAD","notepad.exe"),
													new Pair("CONTROL","control.exe"),
		};

		public static string FindExecuteString(string value)
		{
			foreach (Pair p in ExeNames)
			{
				if (value.Equals(p.Key))
				{
					return value.Replace(p.Key, p.Value);
				}
			}

			return null;
		}

		public static string GetExecuteString(XmlNode node)
		{
			string value = GetValue(node);
			if (string.IsNullOrEmpty(value))
				return string.Empty;

			string exec = FindExecuteString(value);

			if (!string.IsNullOrEmpty(exec))
			{
				return exec;
			}

			return value;
		}

		//TODO ○もっと対応が必要かも。クラスで管理するべきかも。

		static readonly string[] meta = { 
			@"\x",	//0 YY/MM/DD
			@"\0x",	//1 YY/MM/DD
			@"\g",	//2 平成XX年
			@"\m",	//3 YY月
			@"\d",	//4 ZZ日
			@"\B",	//5 January～December
			@"\w",	//6 日～土
			@"\A",	//7 Sunday～Saturday
			@"\X",	//8 （24時間）23:59:00
			@"\r",	//9 （12時間）10:12:30 AM
			@"\Y",	//10 2009
			@"\0m",	//11 YY月
			@"\0d",	//12 ZZ日
		};


		public static string GetValueReplaced(XmlNode node, DateTime now)
		{
			string value = GetValue(node);
			if (string.IsNullOrEmpty(value))
				return string.Empty;

			for (int i = 0; i < meta.Length; i++ )
			{
				if (value.Contains(meta[i]))
				{
					string newValue = string.Empty;
					switch (i)
					{
						case 0:
							newValue = now.ToString("%y/%M/%d");
							break;
						case 1:
							newValue = now.ToString("yy/MM/dd");
							break;
						case 2:
							newValue = now.ToString("gyy", jpCulture_);
							break;
						case 3:
							newValue = now.ToString("MM");
							break;
						case 4:
							newValue = now.ToString("dd");
							break;
						case 5:
							//January～December
							newValue = now.ToString("MMMM", enCulture_);
							break;
						case 6:
							//日～土
							newValue = now.ToString("ddd", jpCulture_);
							break;
						case 7:
							//Sunday～Saturday
							newValue = now.ToString("dddd", enCulture_);
							break;
						case 8:
							newValue = now.ToString("HH:mm:ss");
							break;
						case 9:
							newValue = now.ToString("hh:mm:ss tt", enCulture_);
							break;
						case 10:
							newValue = now.Year.ToString(enCulture_);
							break;
						case 11:
							newValue = now.ToString("MM");
							break;
						case 12:
							newValue = now.ToString("dd");
							break;

						default:
							throw new FundamentalException(global::ClipClop.Properties.Resources.EA001);
					}

					value = value.Replace(meta[i], newValue);
					if (value.Contains(meta[i]))
					{
						//まだあるなら、もう一回
						i--;
					}
				}
			}
			return string.Format(value);
		}		

		public static ContextMenuSettingDefinition.SettingType GetSettingType(XmlNode node)
		{
			if (ContextMenuSettingDefinition.Sentence_ == node.Name)
			{
				return ContextMenuSettingDefinition.SettingType.sentence;
			}

			if (ContextMenuSettingDefinition.Folder_ == node.Name)
			{
				return ContextMenuSettingDefinition.SettingType.folder;
			}

			return ContextMenuSettingDefinition.SettingType.separator;
		}

		public static ContextMenuSettingDefinition.Mode GetMode(XmlNode node)
		{
			if (ContextMenuSettingDefinition.Sentence_ != node.Name)
			{
				throw new FundamentalException(global::ClipClop.Properties.Resources.EA001);
			}

			XmlAttribute attri = node.Attributes[ContextMenuSettingDefinition.Type_];
			if (null == attri)
			{
				throw new FundamentalException(global::ClipClop.Properties.Resources.EA001);
			}

			ContextMenuSettingDefinition.Mode mode = (ContextMenuSettingDefinition.Mode) Enum.Parse(typeof(ContextMenuSettingDefinition.Mode), attri.Value);

			return mode;
		}

		public static bool SetTypeAttribute(XmlNode node, ContextMenuSettingDefinition.Mode mode)
		{
			if (ContextMenuSettingDefinition.Sentence_ == node.Name)
			{
				XmlAttribute attri = node.Attributes[ContextMenuSettingDefinition.Type_];
				if (null == attri)
				{
					//これは必ずあるはず
					return false;
				}
				attri.Value = mode.ToString();
				return true;
			}
			return false;
		}
	}
}
