/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;

namespace Apache.Geode.DUnitFramework
{
  public class XmlNodeReaderWriter
  {
    #region Public accessors, constants and members

    public XmlDocument XmlDoc
    {
      get
      {
        return m_xmlDoc;
      }
    }
    public const string RootNodeName = "Settings";

    #endregion

    #region Statics and constants

    private static Dictionary<string, XmlNodeReaderWriter> instances = new Dictionary<string, XmlNodeReaderWriter>();

    #endregion

    #region Private members

    private FileStream m_xmlStream = null;
    private XmlReader m_xmlReader = null;
    private volatile XmlDocument m_xmlDoc = null;
    private string m_xmlPath = null;

    #endregion

    private void Close()
    {
      if (m_xmlReader != null)
      {
        m_xmlReader.Close();
        m_xmlStream.Close();
      }
    }

    private void ReloadFile(string path)
    {
      XmlReaderSettings xmlSettings = new XmlReaderSettings();
      xmlSettings.IgnoreComments = true;
      m_xmlStream = new FileStream(path, FileMode.Open, FileAccess.Read,
        FileShare.Read);
      m_xmlReader = XmlReader.Create(m_xmlStream, xmlSettings);
      m_xmlDoc = new XmlDocument();
      m_xmlDoc.Load(m_xmlReader);
      m_xmlPath = path;
    }

    private void Save()
    {
      if (m_xmlDoc != null)
      {
        Close();
        m_xmlDoc.Save(m_xmlPath);
        ReloadFile(m_xmlPath);
      }
    }

    /// <summary>
    /// Private constructor to create a ReadConfig instance for the given
    /// configuration file.
    /// </summary>
    /// <param name="path">The path of the XML file to read.</param>
    private XmlNodeReaderWriter(string path)
    {
      try
      {
        if (!File.Exists(path))
        {
          FileStream fs = new FileStream(path, FileMode.Create,
            FileAccess.Write, FileShare.Read);
          if (fs != null)
          {
            byte[] buffer = Encoding.ASCII.GetBytes(string.Format(
              "<?xml version=\"1.0\" encoding=\"utf-8\"?>{0}<{1}>{2}</{3}>{4}",
              Environment.NewLine, RootNodeName, Environment.NewLine,
              RootNodeName, Environment.NewLine));
            fs.Write(buffer, 0, buffer.Length);
            fs.Close();
          }
          else
          {
            m_xmlDoc = null;
            return;
          }
        }
        ReloadFile(path);
      }
      catch
      {
        Close();
        m_xmlDoc = null;
        throw;
      }
    }

    /// <summary>
    /// Get an instance of ReadConfig for the given configuration file.
    /// </summary>
    /// <param name="path">The path of the XML file to read.</param>
    /// <returns>An instance of ReadConfig object to be able to read key/value pairs.</returns>
    public static XmlNodeReaderWriter GetInstance(string path)
    {
      XmlNodeReaderWriter instance = null;
      if (path != null)
      {
        lock (((ICollection)instances).SyncRoot)
        {
          if (instances.ContainsKey(path))
          {
            instance = instances[path];
          }
          else
          {
            instance = new XmlNodeReaderWriter(path);
            instances.Add(path, instance);
          }
        }
      }
      return instance;
    }

    /// <summary>
    /// Remove an instance from the global table.
    /// </summary>
    /// <param name="path">The path of the XML file whose instance is to be removed.</param>
    public static void RemoveInstance(string path)
    {
      if (path != null)
      {
        lock (((ICollection)instances).SyncRoot)
        {
          if (instances.ContainsKey(path))
          {
            XmlNodeReaderWriter instance = instances[path];
            instance.Close();
            instances.Remove(path);
          }
        }
      }
    }

    public static string GetPathForNode(MethodBase method)
    {
      return '/' + RootNodeName + '/' + method.ReflectedType.Name +
        '/' + method.Name;
    }

    public static string GetPathForNode(MethodBase method, string nodeName)
    {
      return GetPathForNode(method.ReflectedType.Name, method.Name, nodeName);
    }

    public static string GetPathForNode(string typeName)
    {
      return '/' + RootNodeName + '/' + typeName;
    }

    public static string GetPathForNode(string typeName, string methodName, string nodeName)
    {
      return '/' + RootNodeName + '/' + typeName +
        '/' + methodName + '/' + nodeName;
    }

    /// <summary>
    /// Select a single XML node having the given xpath.
    /// </summary>
    /// <param name="xpath">The XPath of the node to search.</param>
    /// <returns>The XML node.</returns>
    public XmlNode GetNode(string xpath)
    {
      if (m_xmlDoc != null && xpath != null)
      {
        lock (m_xmlDoc)
        {
          return m_xmlDoc.SelectSingleNode(xpath);
        }
      }
      return null;
    }

    /// <summary>
    /// Select the XML nodes having the given xpath.
    /// </summary>
    /// <param name="xpath">The XPath of the node to search.</param>
    /// <returns>The list of XML nodes.</returns>
    public XmlNodeList GetNodeList(string xpath)
    {
      if (m_xmlDoc != null && xpath != null)
      {
        lock (m_xmlDoc)
        {
          return m_xmlDoc.SelectNodes(xpath);
        }
      }
      return null;
    }

    /// <summary>
    /// Get the innner text of a node using given xpath.
    /// </summary>
    /// <param name="xpath">The XPath of the node to search.</param>
    /// <returns>The value of the node.</returns>
    public string GetValue(string xpath)
    {
      if (m_xmlDoc != null && xpath != null)
      {
        lock (m_xmlDoc)
        {
          XmlNode node = m_xmlDoc.SelectSingleNode(xpath);
          if (node != null)
          {
            return node.InnerText;
          }
        }
      }
      return null;
    }

    /// <summary>
    /// Get the given attribute of a node having the given xpath.
    /// </summary>
    /// <param name="xpath">The XPath of the node to search.</param>
    /// <param name="attribName">The name of the attribute to find.</param>
    /// <returns>The value of the attribute of the node.</returns>
    public string GetAttribute(string xpath, string attribName)
    {
      if (m_xmlDoc != null && xpath != null)
      {
        lock (m_xmlDoc)
        {
          XmlNode node = m_xmlDoc.SelectSingleNode(xpath + "/@" + attribName);
          if (node != null)
          {
            return node.Value;
          }
        }
      }
      return null;
    }

    /// <summary>
    /// Get an attribute of a node for the given XmlNode.
    /// </summary>
    /// <param name="node">The XmlNode to search in.</param>
    /// <param name="xpath">The XPath of the node to search.</param>
    /// <param name="attribName">The name of the attribute to find.</param>
    /// <returns>The value of the attribute of the node.</returns>
    public static string GetAttribute(XmlNode node, string attribName)
    {
      if (node != null)
      {
        XmlAttribute attrib = node.Attributes[attribName];
        if (attrib != null)
        {
          return attrib.Value;
        }
      }
      return null;
    }

    /// <summary>
    /// Get the attributes for nodes having the given xpath.
    /// </summary>
    /// <param name="xpath">The XPath of the nodes to search.</param>
    /// <returns>
    /// List of attributes as key-value pairs for the found nodes.
    /// </returns>
    public List<Dictionary<string, string>> GetAttributes(string xpath)
    {
      if (m_xmlDoc != null)
      {
        lock (m_xmlDoc)
        {
          return GetAttributes(m_xmlDoc, xpath);
        }
      }
      return null;
    }

    /// <summary>
    /// Get the attributes for nodes having the given xpath for the given XmlNode.
    /// </summary>
    /// <param name="node">The XmlNode to search in.</param>
    /// <param name="xpath">The XPath of the nodes to search.</param>
    /// <returns>
    /// List of attributes as key-value pairs for the found nodes.
    /// </returns>
    public static List<Dictionary<string, string>> GetAttributes(
      XmlNode node, string xpath)
    {
      if (xpath != null)
      {
          XmlNodeList nodeList = node.SelectNodes(xpath);
          if (nodeList != null)
          {
            List<Dictionary<string, string>> valueList = new List<Dictionary<string, string>>();
            foreach (XmlNode xmlNode in nodeList)
            {
              Dictionary<string, string> keyValPairs = new Dictionary<string, string>();
              foreach (XmlAttribute xmlAttrib in xmlNode.Attributes)
              {
                keyValPairs.Add(xmlAttrib.Name, xmlAttrib.Value);
              }
              valueList.Add(keyValPairs);
            }
            return valueList;
        }
      }
      return null;
    }

    #region Convenience functions to get attributes

    public static string GetStringValue(XmlNode node, string attribName)
    {
      return GetStringValue(node, attribName, null);
    }

    public static string GetStringValue(XmlNode node, string attribName,
      string defaultValue)
    {
      XmlAttribute xmlAttrib = node.Attributes[attribName];
      if (xmlAttrib != null && xmlAttrib.Value != null)
      {
        return xmlAttrib.Value;
      }
      return defaultValue;
    }

    public static int String2Int(string str, int defaultValue)
    {
      try
      {
        return int.Parse(str);
      }
      catch
      {
        return defaultValue;
      }
    }

    /// <summary>
    /// Get the number of seconds from the string.
    /// </summary>
    /// <remarks>
    /// If the string contains 'h' or 'm' then it is assumed to be in
    /// hours and minutes respectively.
    /// </remarks>
    /// <param name="str">The string to parse.</param>
    /// <param name="defaultValue">
    /// The default value to return if string is null or empty.
    /// </param>
    /// <returns>
    /// The number of seconds;
    /// <paramref name="defaultValue"/> if string is null of empty.
    /// </returns>
    public static int String2Seconds(string str, int defaultValue)
    {
      if (str == null || str.Length == 0)
      {
        return defaultValue;
      }
      int totalSecs = 0;
      int hPos = str.IndexOf('h');
      if (hPos > 0)
      {
        totalSecs += int.Parse(str.Substring(0, hPos)) * 3600;
        str = str.Substring(hPos + 1);
      }
      int mPos = str.IndexOf('m');
      if (mPos > 0)
      {
        totalSecs += int.Parse(str.Substring(0, mPos)) * 60;
        str = str.Substring(mPos + 1);
      }
      if (str != null && str.Length > 0)
      {
        str = str.TrimEnd('s');
        totalSecs += int.Parse(str);
      }
      return totalSecs;
    }

    public static int GetIntValue(XmlNode node, string attribName,
      int defaultValue)
    {
      XmlAttribute xmlAttrib = node.Attributes[attribName];
      if (xmlAttrib != null)
      {
        return String2Int(xmlAttrib.Value, defaultValue);
      }
      return defaultValue;
    }

    public static bool String2Bool(string str, bool defaultValue)
    {
      str = str.ToLower();
      if (str == "true" || str == "yes")
      {
        return true;
      }
      else if (str == "false" || str == "no")
      {
        return false;
      }
      return defaultValue;
    }

    public static bool GetBoolValue(XmlNode node, string attribName,
      bool defaultValue)
    {
      XmlAttribute xmlAttrib = node.Attributes[attribName];
      if (xmlAttrib != null)
      {
        return String2Bool(xmlAttrib.Value, defaultValue);
      }
      return defaultValue;
    }

    #endregion

    /// <summary>
    /// Get the attributes for a node in the given method.
    /// </summary>
    /// <param name="method">The method to search the node.</param>
    /// <param name="nodeName">The name of the node in the given method.</param>
    /// <returns>
    /// List of attributes as key-value pairs for the found nodes.
    /// </returns>
    public List<Dictionary<string, string>> GetValues(MethodBase method, string nodeName)
    {
      string xpath = GetPathForNode(method, nodeName);
      return GetAttributes(xpath);
    }

    /// <summary>
    /// Get the attributes for a node in the given method.
    /// </summary>
    /// <param name="typeName">The class to which the method belongs.</param>
    /// <param name="methodName">The name of the method.</param>
    /// <param name="nodeName">The name of the node in the given method.</param>
    /// <returns>
    /// List of attributes as key-value pairs for the found nodes.
    /// </returns>
    public List<Dictionary<string, string>> GetValues(string typeName, string methodName, string nodeName)
    {
      string xpath = '/' + RootNodeName + '/' + typeName +
        '/' + methodName + '/' + nodeName;
      return GetAttributes(xpath);
    }

    /// <summary>
    /// Convenience method to add a new node with the given path and attributes.
    /// All the ancestors of the node that do not exist are also added.
    /// Normally should not be used rather XML created manually.
    /// </summary>
    /// <param name="nodePath">
    /// The path of the node to add.
    /// This should be a '/' separated path like in XPath.
    /// </param>
    /// <param name="attributes">
    /// Any number of attributes as key value pairs, with a key followed by a value.
    /// If they are not even in number then the last value is taken to be empty.
    /// </param>
    public void AddNodeAttributes(string nodePath, params string[] attributes)
    {
      if (m_xmlDoc != null && nodePath != null)
      {
        string[] nodePathSplit = nodePath.Split('/');
        string nodePartialPath = string.Empty;
        lock (m_xmlDoc)
        {
          XmlNode currNode = m_xmlDoc;
          XmlNode parentNode = m_xmlDoc;
          XmlNode newNode;
          int i;
          for (i = 0; i < nodePathSplit.Length - 1; i++)
          {
            nodePartialPath += '/' + nodePathSplit[i];
            currNode = m_xmlDoc.SelectSingleNode(nodePartialPath);
            if (currNode == null)
            {
              break;
            }
            parentNode = currNode;
          }
          for (int j = i; j < nodePathSplit.Length; j++)
          {
            newNode = m_xmlDoc.CreateElement(nodePathSplit[j]);
            parentNode.AppendChild(newNode);
            parentNode = newNode;
          }
          XmlAttribute xmlAttrib;
          for (i = 0; i < attributes.Length; i += 2)
          {
            xmlAttrib = m_xmlDoc.CreateAttribute(attributes[i]);
            if ((i + 1) < attributes.Length)
            {
              xmlAttrib.Value = attributes[i + 1];
            }
            else
            {
              xmlAttrib.Value = string.Empty;
            }
            parentNode.Attributes.Append(xmlAttrib);
          }
          Save();
        }
      }
    }

    /// <summary>
    /// Delete the first instance of a node with the given path.
    /// </summary>
    /// <param name="nodePath">
    /// The path of the node to delete.
    /// This should be a '/' separated path like in XPath.
    /// </param>
    public void DeleteNode(string nodePath)
    {
      if (m_xmlDoc != null && nodePath != null)
      {
        lock (m_xmlDoc)
        {
          XmlNode node = m_xmlDoc.SelectSingleNode(nodePath);
          if (node != null)
          {
            node.ParentNode.RemoveChild(node);
            Save();
          }
        }
      }
    }

    /// <summary>
    /// Delete all instances of a node with the given path.
    /// </summary>
    /// <param name="nodePath">
    /// The path of the node to delete.
    /// This should be a '/' separated path like in XPath.
    /// </param>
    public void DeleteAllNodes(string nodePath)
    {
      if (m_xmlDoc != null && nodePath != null)
      {
        lock (m_xmlDoc)
        {
          XmlNodeList nodeList = m_xmlDoc.SelectNodes(nodePath);
          if (nodeList != null)
          {
            foreach (XmlNode node in nodeList)
            {
              node.ParentNode.RemoveChild(node);
            }
            Save();
          }
        }
      }
    }

    /// <summary>
    /// Set the attributes for the first instance of a node with the given path.
    /// If the node is not found then it is added (alongwith all its parents).
    /// </summary>
    /// <param name="nodePath">
    /// The path of the node to modify.
    /// This should be a '/' separated path like in XPath.
    /// </param>
    /// <param name="attributes">
    /// The given key value pairs are set as attributes in the first found node.
    /// If they are not even in number then the last value is taken to be empty.
    /// </param>
    public void SetNodeAttributes(string nodePath, params string[] attributes)
    {
      if (m_xmlDoc != null && nodePath != null)
      {
        lock (m_xmlDoc)
        {
          XmlNode xmlNode = m_xmlDoc.SelectSingleNode(nodePath);
          if (xmlNode != null)
          {
            xmlNode.Attributes.RemoveAll();
            XmlAttribute xmlAttrib;
            for (int i = 0; i < attributes.Length; i += 2)
            {
              xmlAttrib = m_xmlDoc.CreateAttribute(attributes[i]);
              if ((i + 1) < attributes.Length)
              {
                xmlAttrib.Value = attributes[i + 1];
              }
              else
              {
                xmlAttrib.Value = string.Empty;
              }
              xmlNode.Attributes.Append(xmlAttrib);
            }
            Save();
          }
          else
          {
            AddNodeAttributes(nodePath, attributes);
          }
        }
      }
    }

    /// <summary>
    /// Create a XmlNode from a given XML string.
    /// </summary>
    /// <param name="xmlString">The XML string for a node.</param>
    /// <returns>The XMLNode created from the given string.</returns>
    public static XmlNode CreateXmlNode(string xmlString)
    {
      XmlDocument xmlDoc = new XmlDocument();
      xmlDoc.LoadXml(xmlString);
      return xmlDoc.FirstChild;
    }
  }
}
