using System;
using System.Xml;
using System.Windows.Forms;
using System.Text;
using System.Reflection;
using System.IO;

namespace TreeViewSerialization
{
	/// <summary>
	/// Summary description for TreeViewSerializer.
	/// </summary>
	public class TreeViewSerializer
	{
		
		// Xml tag for node, e.g. 'node' in case of <node></node>
		private const string XmlNodeTag = "fixlet";
		
		// Xml attributes for node e.g. <node text="Asia" tag="" imageindex="1"></node>
		private const string XmlNodeTextAtt = "text";
		private const string XmlNodeTagAtt = "tag";
        private const string XmlNodeImageIndexAtt = "imageindex";

		public TreeViewSerializer()
		{
			//
			// TODO: Add constructor logic here
			//
		}

		//System.IO.StringWriter s;
		public void SerializeTreeView(TreeView treeView, string fileName) 
		{
			XmlTextWriter textWriter = new XmlTextWriter(fileName, System.Text.Encoding.ASCII);
			// writing the xml declaration tag
			textWriter.WriteStartDocument();
			//textWriter.WriteRaw("\r\n");
			// writing the main tag that encloses all node tags
			textWriter.WriteStartElement("FixletType");
			
			// save the nodes, recursive method
			SaveNodes(treeView.Nodes, textWriter);
			
			textWriter.WriteEndElement();
					
			textWriter.Close();
		}

		private void SaveNodes(TreeNodeCollection nodesCollection, 
			XmlTextWriter textWriter)
		{
			for(int i = 0; i < nodesCollection.Count; i++)
			{
				TreeNode node = nodesCollection[i];
				textWriter.WriteStartElement(XmlNodeTag);
				textWriter.WriteAttributeString(XmlNodeTextAtt, node.Text);
				textWriter.WriteAttributeString(XmlNodeImageIndexAtt, node.ImageIndex.ToString());
				if(node.Tag != null) 
					textWriter.WriteAttributeString(XmlNodeTagAtt, node.Tag.ToString());
				
				// add other node properties to serialize here
				
				if (node.Nodes.Count > 0)
				{
					
					SaveNodes(node.Nodes, textWriter);
					    
				} 				
				textWriter.WriteEndElement();
			}
		}		

		public void DeserializeTreeView(TreeView treeView, string fileName, string besTag)
		{
 
            XmlTextReader reader = null;
            
			try
			{
                // New from Lee Wei
                // System.Reflection.Assembly asm = System.Reflection.Assembly.Load(assemblyName);
                System.Reflection.Assembly asm = System.Reflection.Assembly.GetExecutingAssembly();
                Stream str = asm.GetManifestResourceStream(asm.GetName().Name + "." + fileName);
                // MessageBox.Show("Assembly name: " + asm.GetName().Name);

                if (str == null)
                    throw new Exception("Could not locate embedded resource '" + fileName + "' in assembly '" + asm.GetName().Name + "'");
                // End Lee Wei

                // disabling re-drawing of treeview till all nodes are added
				treeView.BeginUpdate();				
				// reader = new XmlTextReader(fileName);
                reader = new XmlTextReader(str);

				TreeNode parentNode = null;
				
				while (reader.Read())
				{
					if (reader.NodeType == XmlNodeType.Element)
					{						
                        if (reader.Name == besTag)
						// if (reader.Name == XmlNodeTag)
						{
							TreeNode newNode = new TreeNode();
							bool isEmptyElement = reader.IsEmptyElement;

                            // loading node attributes
							int attributeCount = reader.AttributeCount;
							if (attributeCount > 0)
							{
								for (int i = 0; i < attributeCount; i++)
								{
									reader.MoveToAttribute(i);
									
									SetAttributeValue(newNode, reader.Name, reader.Value);
								}								
							}

                            // add new node to Parent Node or TreeView
                            if(parentNode != null)
                                parentNode.Nodes.Add(newNode);
                            else
                                treeView.Nodes.Add(newNode);

                            // making current node 'ParentNode' if its not empty
							if (!isEmptyElement)
							{
                                parentNode = newNode;
							}
														
						}						                    
					}
                    // moving up to in TreeView if end tag is encountered
					else if (reader.NodeType == XmlNodeType.EndElement)
					{
                        // if (reader.Name == XmlNodeTag)
                        if (reader.Name == besTag)
						{
							parentNode = parentNode.Parent;
						}
					}
					else if (reader.NodeType == XmlNodeType.XmlDeclaration)
					{ //Ignore Xml Declaration                    
					}
					else if (reader.NodeType == XmlNodeType.None)
					{
						return;
					}
					else if (reader.NodeType == XmlNodeType.Text)
					{
						parentNode.Nodes.Add(reader.Value);
					}

				}
			}
			finally
			{
                // enabling redrawing of treeview after all nodes are added
				treeView.EndUpdate();      
                reader.Close();	
			}
		}

		/// <summary>
		/// Used by Deserialize method for setting properties of TreeNode from xml node attributes
		/// </summary>
		/// <param name="node"></param>
		/// <param name="propertyName"></param>
		/// <param name="value"></param>
		private void SetAttributeValue(TreeNode node, string propertyName, string value)
		{
			if (propertyName == XmlNodeTextAtt)
			{                
				node.Text = value;				
			}
			else if (propertyName == XmlNodeImageIndexAtt) 
			{
				node.ImageIndex = int.Parse(value);
			}
			else if (propertyName == XmlNodeTagAtt)
			{
				node.Tag = value;
			}		
		}

        public void LoadXmlFileInTreeView(TreeView treeView, string fileName)
        {
            XmlTextReader reader = null;
            try
            {
                treeView.BeginUpdate();
                reader = new XmlTextReader(fileName);

                TreeNode n = new TreeNode(fileName);
                treeView.Nodes.Add(n);
                while(reader.Read())
                {
                    if(reader.NodeType == XmlNodeType.Element)
                    {
                        bool isEmptyElement = reader.IsEmptyElement;
                        StringBuilder text = new StringBuilder();
                        text.Append(reader.Name);
                        int attributeCount = reader.AttributeCount;
                        if(attributeCount > 0)
                        {
                            text.Append(" ( ");
                            for(int i = 0; i < attributeCount; i++)
                            {
                                if(i!=0) text.Append(", ");
                                reader.MoveToAttribute(i);
                                text.Append(reader.Name);
                                text.Append(" = ");
                                text.Append(reader.Value);
                            }
                            text.Append(" ) ");
                        }
            
                        if(isEmptyElement)
                        {
                            n.Nodes.Add(text.ToString());
                        }
                        else
                        {
                            n = n.Nodes.Add(text.ToString());
                        }
                    }
                    else if(reader.NodeType == XmlNodeType.EndElement)
                    {
                        n = n.Parent;                    
                    }
                    else if(reader.NodeType == XmlNodeType.XmlDeclaration)
                    {
                    
                    }
                    else if(reader.NodeType == XmlNodeType.None) 
                    {
                        return;
                    }
                    else if(reader.NodeType == XmlNodeType.Text)
                    {
                        n.Nodes.Add(reader.Value);
                    }

                }        
            }
            finally
            {
                treeView.EndUpdate();
                reader.Close();
            }
        }

	}
}
