using EasyDevCore.Common;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace EasyDev.Database.EntityTable
{
    /// <summary>
    /// 
    /// </summary>
    public static class SerializerExtensions
    {
        /// <summary>
        /// Converts to xmlraw.
        /// </summary>
        /// <param name="table">The table.</param>
        /// <param name="rowName">Name of the row.</param>
        /// <param name="documentName">Name of the document.</param>
        /// <returns></returns>
        public static string ToRawXml(this DataTable table, string rowName = "Row", string documentName = null)
        {
            if (string.IsNullOrWhiteSpace(documentName)) documentName = "DATA";
            using (StringWriter sw = new StringWriter())
            {
                sw.WriteLine(string.Format(@"<{0} xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"">", documentName));
                foreach (DataRow row in table.Rows)
                {
                    sw.WriteLine(string.Format("<{0}>", rowName));
                    foreach (DataColumn col in table.Columns)
                    {
                        object value = row.GetValue(col.Ordinal);
                        if (value == null)
                        {
                            sw.WriteLine(string.Format("<{0} xsi:nil=\"true\"/>", XmlConvert.EncodeName(col.ColumnName)));
                        }
                        else
                        {
                            sw.WriteLine(string.Format("<{0}>{1}</{0}>", XmlConvert.EncodeName(col.ColumnName), System.Security.SecurityElement.Escape(value.StringFrom())));
                        }
                    }
                    sw.WriteLine(string.Format("</{0}>", rowName));
                }
                sw.WriteLine(string.Format(@"</{0}>", documentName));
                return sw.ToString();
            }
        }

        /// <summary>
        /// Converts to xml.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="elementName">Name of the element.</param>
        /// <param name="forSynchValues">if set to <c>true</c> [for synch values].</param>
        /// <param name="columnNames">The column names.</param>
        /// <param name="exceptColumnNames">The except column names.</param>
        /// <param name="keyFields">The key fields.</param>
        /// <param name="omitXmlDeclaration">if set to <c>true</c> [omit XML declaration].</param>
        /// <param name="proxyShema">The proxy shema.</param>
        /// <param name="optimumSize">if set to <c>true</c> [optimum size].</param>
        /// <returns></returns>
        public static string ToXml(this DataTable source, string elementName = null, bool forSynchValues = false, string columnNames = "", string exceptColumnNames = "", string keyFields = "", bool omitXmlDeclaration = false, DataTableSerializerSchema proxyShema = DataTableSerializerSchema.None, bool optimumSize = true)
        {
            StringBuilder sb = new StringBuilder();
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.OmitXmlDeclaration = omitXmlDeclaration;
            using (XmlWriter writer = XmlWriter.Create(sb, settings))
            {
                if (elementName == null) elementName = typeof(DataTableSerializer).Name;
                XmlRootAttribute xRoot = new XmlRootAttribute();
                xRoot.ElementName = elementName;
                XmlSerializer serializer = new XmlSerializer(typeof(DataTableSerializer), xRoot);
                DataTableSerializer ps = new DataTableSerializer(source, forSynchValues, columnNames, exceptColumnNames, keyFields, proxyShema, optimumSize);
                serializer.Serialize(writer, ps);
            }
            return sb.ToString();
        }

        /// <summary>
        /// Gets the table from XML.
        /// </summary>
        /// <param name="xml">The XML.</param>
        /// <param name="rootName">Name of the root.</param>
        /// <returns></returns>
        public static DataTable GetTableFromXML(this string xml, string rootName = null)
        {
            using (StringReader sr = new StringReader(xml))
            {
                if (rootName == null)
                    rootName = typeof(DataTableSerializer).Name;
                XmlRootAttribute xRoot = new XmlRootAttribute(rootName);
                xRoot.ElementName = rootName;
                XmlSerializer serializer = new XmlSerializer(typeof(DataTableSerializer), xRoot);
                DataTableSerializer px = (DataTableSerializer)serializer.Deserialize(sr);
                return px.Table;
            }
        }
    }
}
