using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
using System.Globalization;

namespace VisiMath
{
    /// <summary>
    /// Static helper class for XML import / export
    /// </summary>
    public static class XMLHelper
    {
        /// <summary>
        /// Default culture info
        /// </summary>
        public static readonly CultureInfo CF = new CultureInfo("en-US");
        
        /// <summary>
        /// Culture independent string / numeric conversion. Use bool FloatFromString(string str, out float) if you need to know if conversion was succesfull
        /// </summary>
        /// <remarks>Stupid NET and ToString() automatically using local globalization settings</remarks>
        /// <param name="str">String to parse</param>
        /// <returns>Float value in string or 0</returns>
        public static float FloatFromString(string str)
        {
            double rval;
            try
            {
                rval = Convert.ToDouble(str, CF);
                return (float)rval;
            }
            catch
            {
                return 0;
            }
        }

        /// <summary>
        /// Culture independent string/numeric conversion.
        /// </summary>
        /// <param name="str">String</param>
        /// <param name="val">float value</param>
        /// <returns>True if conversion sucessful</returns>
        public static bool FloatFromString(string str, out float val)
        {
            val = 0;
            try
            {
                val = (float)Convert.ToDouble(str, CF);
                return true;
            }
            catch
            {
                return false;
            }
        }


        /// <summary>
        /// Tries to read float value from XML reader
        /// </summary>
        /// <param name="reader">XML reader</param>
        /// <param name="throwonfailure">If set to true, will throw exception if content is not float</param>
        /// <returns>Float value</returns>
        public static float ReadAsFloat(XmlReader reader, bool throwonfailure = false)
        {
            float value;
            if (FloatFromString(reader.ReadString(), out value))
                return value;
            if (throwonfailure)
                throw new ArgumentException("XML doesn't contain float value");
            return 0;
        }

        /// <summary>
        /// Tries to read Int value from XML reader
        /// </summary>
        /// <param name="reader">XML reader</param>
        /// <param name="throwonfailure">If set to true, will throw exception if content is not float</param>
        /// <returns>Int value</returns>
        public static int ReadAsInt(XmlReader reader, bool throwonfailure = false)
        {
            int val;
            if (int.TryParse(reader.ReadString(), out val))
                return val;
            if (throwonfailure)
                throw new ArgumentException("XML doesn't contain int value");
            return 0;
        }

        /// <summary>
        /// Read value in reader as bool
        /// </summary>
        /// <param name="reader">XML reader</param>
        /// <param name="throwonfailure">If true, exception will be thrown on reading failure</param>
        /// <returns>Bool value</returns>
        public static bool ReadAsBool(XmlReader reader, bool throwonfailure = false)
        {
            string str = reader.ReadString();
            if (str == "False")
                return false;
            if (str == "True")
                return true;
            if (throwonfailure)
                throw new ArgumentException("XML doesn't contain bool value");
            return false;
        }

        /// <summary>
        /// Write float value to xml
        /// </summary>
        /// <param name="writer">xml writer</param>
        /// <param name="RootNode">Node to write number</param>
        /// <param name="val">Number to write</param>
        public static void WriteFloat(XmlWriter writer, string RootNode, float val)
        {
            writer.WriteElementString(RootNode, val.ToString(CF));
        }

        /// <summary>
        /// Write float as attribute
        /// </summary>
        /// <param name="writer">XML writer</param>
        /// <param name="attr">Attribute name</param>
        /// <param name="val">Numeric value</param>
        public static void WriteFloatAttribute(XmlWriter writer, string attr, float val)
        {
            writer.WriteAttributeString(attr, val.ToString(CF));
        }

        /// <summary>
        /// Read Vector3 from XML
        /// </summary>
        /// <param name="reader">XML reader</param>
        /// <returns>Vector3 value</returns>
        public static Vector3 ReadVector3(XmlReader reader)
        {
            Vector3 vec = new Vector3();
            vec.ReadXml(reader);
            return vec;
        }
    }
}
