using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml;
using System.IO;

using EQNetwork.Objects;
using EQNetwork.Utility;

namespace EQNetwork.Services
{   
    public partial class EQApiService : System.IDisposable, EQNetwork.Interfaces.IEQApiService
    {
        private bool _cancelled = false;

        public Dictionary<HttpWebRequest, HttpWebRequest> _requests = new Dictionary<HttpWebRequest, HttpWebRequest>();

        private EQProcess _eq;
        public EQApiService(EQProcess eq)
        {
            _eq = eq;
        }

        public void CancelAll()
        {
            _cancelled = true;
            lock (_requests)
            {
                foreach (var request in _requests.Keys)
                    request.Abort();
            }
        }

        public HttpWebResponse MakeApi2Request(string page, Parameters parms)
        {
            string url = System.IO.Path.Combine("http://jdidb.eqnetwork.com/Api2.0/", page + ".aspx");

            List<string> names = new List<string>();
            List<FileUploadSpec> files = new List<FileUploadSpec>();
            foreach (var key in parms.Keys)
                if (parms[key] != null && parms[key].GetType() == typeof(FileUploadSpec))
                {
                    if (((FileUploadSpec)parms[key]).FieldName == null)
                        ((FileUploadSpec)parms[key]).FieldName = key;
                    names.Add(key);
                    files.Add((FileUploadSpec)parms[key]);
                }
            foreach (var key in names)
                parms.Remove(key);

            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            request.Method = "POST";

            if (files == null || files.Count == 0)
            {
                request.ContentType = "application/x-www-form-urlencoded";

                string queryString = AuthUtil.AuthenticateRequest("POST", url, _eq.AccessKey, _eq.Secret, parms.GetUrlEncodedString());

                byte[] bytedata = Encoding.UTF8.GetBytes(queryString);
                request.ContentLength = bytedata.Length;
                Stream requestStream = request.GetRequestStream();
                requestStream.Write(bytedata, 0, bytedata.Length);
                requestStream.Close();
            }
            else
            {
                string queryString = AuthUtil.AuthenticateRequest("POST", url, _eq.AccessKey, _eq.Secret, parms.GetUrlEncodedString());
                var dict = AuthUtil.QueryStringToDictionary(queryString);
                var parms2 = new Parameters();
                foreach (var pair in dict)
                    parms2.Add(pair.Key, pair.Value);
                
                HttpUploadHelper.Upload(request, files, parms2);
            }

            return (HttpWebResponse)request.GetResponse();
        }

        public static XmlNode ParseXml(WebResponse response)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(response.GetResponseStream());
            return ParseXml(doc);
        }

        private static XmlNode ParseXml(HttpWebResponse response)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(response.GetResponseStream());
            return ParseXml(doc);
        }

        private static XmlNode ParseXml(XmlDocument doc)
        {
            XmlNode root = doc.FirstChild;
            if (root == null)
                throw new EQException(0, "The Xml Response is Empty");

            XmlNode node = root.FirstChild;
            if (node != null && string.Equals(node.Name, "Error", StringComparison.OrdinalIgnoreCase))
            {
                int code = int.Parse(node.Attributes["code"].Value);
                string message = node.InnerText;
                throw new EQException(code, message);
            }

            return root;
        }

        #region IDisposable Members
        
        public IDisposable IDisposable { get { return this; } }
        void IDisposable.Dispose()
        {
            CancelAll();
        }

        #endregion
    }
}
