using System;
using System.Xml;
using System.Xml.XPath;
using System.IO;
namespace Config
{
	/// <summary>
	/// Class1 的摘要说明。
	/// </summary>
	public class ConfigFile:IDisposable
	{
		private XmlDocument xmlconfig;
		private string configfilepath=@".\Appstart.config";
		private class AppStartConfig{
			string starterconfig="";
			public AppStartConfig(string file){
				starterconfig=file;
			}
			public void ChangeAppStartPath(string startpath){
				XmlDocument doc=new XmlDocument();
				doc.Load(starterconfig);
				XmlNodeList nodes=doc.GetElementsByTagName("appFolderName");
				if(nodes.Count>0)
					nodes[0].InnerText=startpath;
				doc.Save(starterconfig);
			}
		}
		public ConfigFile(string path)
		{
			configfilepath=path;
			xmlconfig=new XmlDocument();
			xmlconfig.Load(path);
		}
		/// <summary>
		/// 设置日志路径
		/// </summary>
		/// <param name="path"></param>
		public void SetLogPath(string path){
			XmlDocument doc=new XmlDocument();
			doc.Load(configfilepath);
			XmlNodeList nodes=doc.GetElementsByTagName("logListener");
			if(path.Length>0)
			{
				XmlNode node=null;
				if(nodes.Count>0)
					node=nodes[0];
				else
				{
					node=doc.CreateElement("logListener");
					XmlAttribute attr=doc.CreateAttribute("logPath");
					node.Attributes.Append(attr);
					doc.SelectSingleNode("configuration/appUpdater/UpdaterConfiguration").AppendChild(node);
				}
				node.Attributes["logPath"].Value=path;	
			}
			else{
				XmlNode node=doc.SelectSingleNode("configuration/appUpdater/UpdaterConfiguration/logListener");
				if(node!=null)
					node.ParentNode.RemoveChild(node);
			}
			SetEMABLogPulish(path.Length>0,doc);

			doc.Save(configfilepath);
		}

		/// <summary>
		/// 设置是否通过Exception Managment Application Block发布日志到Event log
		/// </summary>
		/// <param name="enable"></param>
		private void SetEMABLogPulish(bool enable,XmlDocument doc){
			XmlNode node=doc.SelectSingleNode("configuration/exceptionManagement");
			if(enable)
				node.Attributes["mode"].Value="on";
			else
				node.Attributes["mode"].Value="off";
		}


		
		/// <summary>
		/// 配置文件路径变更，包括Appstart的配置
		/// </summary>
		/// <param name="Appname"></param>
		/// <param name="newPath"></param>
		public void ChangePath(string Appname,string newPath){
			try
			{
				//更改应用程序配置信息
				ChangeAppConfigPathOnly(Appname,newPath);
				//更改Appstarter启动目录信息
				string basedir=GetPathFullName(newPath);
				AppStartConfig starterconfig=new AppStartConfig(basedir+"AppStart.exe.config");
				starterconfig.ChangeAppStartPath(basedir+"1.0.0.0");
			}
			catch(Exception ex){
				throw new ConfigException("更改配置文件时产生错误！",ex);
			}	
		}
		/// <summary>
		/// 改变应用程序配置文件路径
		/// </summary>
		/// <param name="Appname"></param>
		/// <param name="newPath"></param>
		public void ChangeAppConfigPathOnly(string Appname,string newPath){
			try
			{
				//更改应用程序配置信息
				ChangeApplicationPath(Appname,newPath);
				ChangelogListener(newPath);
				xmlconfig.Save(configfilepath);
			}
			catch(Exception ex)
			{
				throw new ConfigException("更改配置文件时产生错误！",ex);
			}
		}
		public int UpdateInterval{
			get{return GetUpdateInterval();}
			set{SetUpdateInterval(value);}
		}
		/// <summary>
		/// 设置更新间隔
		/// </summary>
		/// <param name="interval"></param>
		private void SetUpdateInterval(int interval){
			XmlNode node=GetPollingNode();
			node.Attributes["type"].Value="Seconds";
			node.Attributes["value"].Value=interval.ToString();
			xmlconfig.Save(configfilepath);
			
		}
		/// <summary>
		/// 获取更新间隔
		/// </summary>
		/// <returns></returns>
		private int GetUpdateInterval(){
			XmlNode node=GetPollingNode();
			int ival=Convert.ToInt32(node.Attributes["value"].Value);
			string strunit=node.Attributes["type"].Value;
			return ToSeconds(ival,strunit);
		}
		private XmlNode GetPollingNode(){
			XmlNodeList node=GetXmlNode("polling");
			if(node.Count>0)
			{
				return node[0];
			}
			else
				throw new ConfigException("未找到Polling节点,请确认配置文件!");
		}
		public int ToSeconds(int ivalue,string unit){
			switch(unit.ToUpper()){
				case "SECONDS":
					return ivalue;
				case "MINUTES":
					return ivalue*60;
				case "HOURS":
					return ivalue*3600;
				default:
					throw new ConfigException("请使用小的单位（秒/分钟/小时）");
			}
		}
		/// <summary>
		/// 更改应用程序节点路径
		/// </summary>
		/// <param name="newpath"></param>
		private void ChangeApplicationPath(string appname,string newpath){
			XmlNodeList node=GetXmlNode("application");
			if(node.Count>0)
			{
				node[0].Attributes["name"].InnerText=appname;
				XmlNode nodetmp=node[0].SelectSingleNode(@"descendant::baseDir");
				ChangeXmlNodeInnerText(nodetmp,newpath);
				nodetmp=node[0].SelectSingleNode(@"descendant::xmlFile");
				ChangeXmlNodeInnerText(nodetmp,GetPathFullName(newpath)+Path.GetFileName(nodetmp.InnerText));
				nodetmp=node[0].SelectSingleNode(@"descendant::tempDir");
				nodetmp.InnerText=GetPathFullName(newpath)+"DownloadFiles";
				nodetmp=node[0].SelectSingleNode(@"descendant::xmlFileDest");
				ChangeXmlNodeInnerText(nodetmp,GetPathFullName(newpath)+Path.GetFileName(nodetmp.InnerText));
			}
		}

		
		private void ChangeXmlNodeInnerText(XmlNode node,string innertext){
			node.InnerText=innertext;
		}
		
		private void ChangelogListener(string newpath){
			XmlNodeList node=GetXmlNode("logListener");
			if(node.Count>0){
				node[0].Attributes["logPath"].InnerText=GetPathFullName(newpath)+Path.GetFileName(node[0].Attributes["logPath"].InnerText);	
			}
		}
		private string GetPathFullName(string path){
			if(path.Length>0)
				if(path.Substring(path.Length-1,1)!=@"\")
					return path+@"\";
			return path;
		}
		private XmlNodeList GetXmlNode(string nodename){
			return xmlconfig.GetElementsByTagName(nodename);
		}
		public void Dispose(){
			xmlconfig=null;
		}
	}
	public class ConfigException: ApplicationException
	{
		public ConfigException():base(){}
		public ConfigException(string message):base(message){}
		public ConfigException(string message, Exception innerException):base(message,innerException){}
	}
}