using System;
using System.Collections;
using System.IO;
using System.Net;
using System.Xml;
using System.Xml.Serialization;
using System.Web;
using System.Text;
using System.Collections.Generic;
using System.Net.Cache;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;

using Betfair.Gamex.API.Entities;

namespace Betfair.Gamex.API
{
    /// <summary>
    /// Parameters for betsnapshot
    /// </summary>
	public enum BetSnapshotBetStatus
    {
        /// <summary>
        /// Bets currently active
        /// </summary>
        ACTIVE, 

        /// <summary>
        /// Cancelled bets
        /// </summary>
        CANCELLED,

        /// <summary>
        /// Lapsed bets
        /// </summary>
        LAPSED, 

        /// <summary>
        /// Matched bets
        /// </summary>
        MATCHED,

        /// <summary>
        /// Voided bets
        /// </summary>
        VOIDED,

        /// <summary>
        /// Unmatched bets
        /// </summary>
        UNMATCHED
    };

    /// <summary>
    /// Parameters for betsnapshot
    /// </summary>
    public enum BetSnapshotOrderBy 
    {
        /// <summary>
        /// Date bet was placed
        /// </summary>
        placedDate, 

        /// <summary>
        /// Market bet was placed on
        /// </summary>
        marketName 
    };

    /// <summary>
    /// Parameters for bet history
    /// </summary>
	public enum BetHistoryBetStatus 
    {
        /// <summary>
        /// Cancelled bets
        /// </summary>
        CANCELLED, 

        /// <summary>
        /// Lapsed bets
        /// </summary>
        LAPSED, 

        /// <summary>
        /// Settled bets
        /// </summary>
        SETTLED, 

        /// <summary>
        /// Voided bets
        /// </summary>
        VOIDED
    };

	/// <summary>
	/// Manages HTTP requests to the Gamex REST API (GAPI)
	/// </summary>
	public class Adapter
	{
        /// <summary>
        /// Enum list of urls provided by API
        /// </summary>
		public enum ApiService
        {
            /// <summary>
            /// API Landing
            /// </summary>
            Landing, 

            /// <summary>
            /// API Landing
            /// </summary>
            V1Landing, 

            /// <summary>
            /// Account landing
            /// </summary>
            AccountLanding, 

            /// <summary>
            /// Account snapshot
            /// </summary>
            AccountSnapshot,

            /// <summary>
            /// Betfair account snapshot
            /// </summary>
            AccountBetfairSnapshot,

            /// <summary>
            /// Account statement
            /// </summary>
            AccountStatement, 

            /// <summary>
            /// Transfer funds
            /// </summary>
            AccountTransferOrder,

            /// <summary>
            /// Bet landing 
            /// </summary>
            BetLanding,

            /// <summary>
            /// Current bets
            /// </summary>
            BetSnapshot,

            /// <summary>
            /// Bet history
            /// </summary>
            BetHistory,

            /// <summary>
            /// Place bets
            /// </summary>
            BetOrder,

            /// <summary>
            /// Channel landing
            /// </summary>
            ChannelLanding,

            /// <summary>
            /// Channel snapshot
            /// </summary>
            ChannelSnapshot,

            /// <summary>
            /// Channel history
            /// </summary>
            ChannelHistory, 

            /// <summary>
            /// Channel info
            /// </summary>
            ChannelInfo,

            /// <summary>
            /// Ping test
            /// </summary>
            Ping
        };

		private const string PasswordHeaderName = "gamexAPIPassword";
		private const string ProcessTimeHeaderName = "processTime";

		private string m_BaseUrl;
		private string m_BetfairUsername;
		private string m_BetfairPassword;
        private string m_SsoToken;

        private string m_RequestedUrl;
        private string m_RequestXml;
        private string m_ResponseXml;

        // timer to log time of entire method call
        private PerformanceTimer m_OverallTimer = new PerformanceTimer();
        private int m_OverallTimeTaken;
        private int m_SerializationTimeTaken;

        // timer to log time of request to server (transit + server execution)
        private PerformanceTimer m_RequestTimer = new PerformanceTimer();
        private int m_RequestTimeTaken;
        private int m_NetworkTimeTaken;
        private int m_ServerTimeTaken;

        private bool m_OutputXml;
        private bool m_SendPassword = true;
        private bool m_SendAgent = true;
        private bool m_SendAgentInstance = true;
        private bool m_AllowExtendedTimings = false;

        private Dictionary<string, string> m_ExtraHeaders = new Dictionary<string, string>();

        // extra timing info
        private Dictionary<string, int> m_ExtendedTimings;

        private string m_APIAgent;

        /// <summary>
        /// Constructor
        /// </summary>
        internal Adapter()
        {
            _SSLCertificateOverride();
        }

        /// <summary>
        /// Constructor
        /// </summary>
        public Adapter(string baseUrl, string apiAgent, string betfairUsername, string betfairPassword) : this()
        {
            m_BaseUrl = baseUrl;
            m_APIAgent = apiAgent;
            m_BetfairUsername = betfairUsername;
            m_BetfairPassword = betfairPassword;

            if (string.IsNullOrEmpty(apiAgent) == true)
            {
                throw new ArgumentException("APIAgent can not be null", "apiAgent");
            }
        }

        /// <summary>
        /// Constructor
        /// </summary>
        public Adapter(string baseUrl, string apiAgent, string ssoToken) : this(baseUrl, apiAgent, null, null)
        {
            m_SsoToken = ssoToken;
        }

        #region Public Properties
        /// <summary>
        /// The last requested url
        /// </summary>
        public string RequestedUrl
        {
            get
            {
                return m_RequestedUrl;
            }
        }

        /// <summary>
        /// The post data for the last request
        /// </summary>
        public string RequestXml
        {
            get
            {
                return m_RequestXml;
            }
        }

        /// <summary>
        /// The xml response from the API
        /// </summary>
        public string ResponseXml
		{
            get
            {
                return m_ResponseXml;
            }
		}

        /// <summary>
        /// The agent identifier for this request (possibly application name)
        /// </summary>
        public string APIAgent
        {
            get
            {
                return m_APIAgent;
            }
        }

        /// <summary>
        /// Whether or not to send the password in the header
        /// </summary>
        public bool SendPassword
        {
            get
            {
                return m_SendPassword;
            }
            set
            {
                m_SendPassword = value;
            }
        }

        /// <summary>
        /// Whether or not to send the Agent header
        /// </summary>
        public bool SendAgent
        {
            get
            {
                return m_SendAgent;
            }
            set
            {
                m_SendAgent = value;
            }
        }

        /// <summary>
        /// Whether or not to send the agent instance header (machine name of request)
        /// </summary>
        public bool SendAgentInstance
        {
            get
            {
                return m_SendAgentInstance;
            }
            set
            {
                m_SendAgentInstance = value; 
            }
        }

        /// <summary>
        /// Allows user to specify more headers
        /// </summary>
        public Dictionary<string, string> ExtraHeaders
        {
            get
            {
                return m_ExtraHeaders;
            }
        }

        /// <summary>
        /// Extra timing response from server - output only
        /// </summary>
        public Dictionary<string, int> ExtendedTimings
        {
            get
            {
                return m_ExtendedTimings; 
            }
        }

        /// <summary>
        /// Whether or not to output xml to the console
        /// </summary>
        public bool OutputXml
        {
            get
            {
                return m_OutputXml;
            }
            set
            {
                m_OutputXml = value; 
            }
        }

        /// <summary>
        /// Return extended timings in the response header
        /// </summary>
        public bool AllowExtendedTimings
        {
            get
            {
                return m_AllowExtendedTimings; 
            }
            set
            {
                m_AllowExtendedTimings = value; 
            }
        }
        #endregion

        #region Serialization
        /// <summary>
        /// Serialize an object from Xml
        /// </summary>
        /// <param name="objectType">Type of object to create</param>
        /// <param name="rawXml">Xml to serialize</param>
        /// <returns>Object</returns>
        public object _DeSerialize(Type objectType, string rawXml)
		{
			XmlSerializer processor = new XmlSerializer(objectType);
			using (StringReader sr = new StringReader(rawXml))
			{
				return processor.Deserialize(sr);
			}
		}

        /// <summary>
        /// Serialize an object into Xml
        /// </summary>
        /// <param name="objectType">Type of object</param>
        /// <param name="o">Object to serialize</param>
        /// <returns>Xml representing object</returns>
		private string _Serialize(Type objectType, object o)
		{
			// serializing an object into Xml
			XmlSerializer processor = new XmlSerializer(objectType);
			using (MemoryStream memStream = new MemoryStream()) 
			{
				XmlTextWriter xtw = new XmlTextWriter(memStream, Encoding.UTF8);
				processor.Serialize(xtw, o);
                xtw.Close();

                // create clean Xml with no whitespace
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.LoadXml(Encoding.UTF8.GetString(memStream.GetBuffer()).Trim());
                xmlDoc.PreserveWhitespace = false;

                return xmlDoc.OuterXml;
			}
        }
        #endregion

        #region HttpMethods
        /// <summary>
        /// Get url for each specific request
        /// </summary>
        /// <param name="serviceName"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private string _GetTargetUri(ApiService serviceName, Hashtable parameters)
        {
            string path = string.Empty;
            switch (serviceName)
            {
                case ApiService.Landing:
                    path = "/rest";
                    break;
                case ApiService.V1Landing:
                    path = "/rest/v1?username={$username}";
                    break;
                case ApiService.AccountLanding:
                    path = "/rest/v1/account?username={$username}";
                    break;
                case ApiService.AccountSnapshot:
                    path = "/rest/v1/account/snapshot?username={$username}";
                    break;
                case ApiService.AccountBetfairSnapshot:
                    path = "/rest/v1/account/betfair/snapshot?username={$username}";
                    break;
                case ApiService.AccountStatement:
                    path = "/rest/v1/account/statement?username={$username}";
                    break;
                case ApiService.AccountTransferOrder:
                    path = "/rest/v1/account/transferOrder?username={$username}";
                    break;
                case ApiService.BetLanding:
                    path = "/rest/v1/bet?username={$username}";
                    break;
                case ApiService.BetSnapshot:
                    path = "/rest/v1/bet/snapshot?username={$username}&betStatus={$betStatus}&orderBy={$orderBy}";
                    break;
                case ApiService.BetHistory:
                    path = "/rest/v1/bet/history?username={$username}&betStatus={$betStatus}";
                    break;
                case ApiService.BetOrder:
                    path = "/rest/v1/bet/order?username={$username}";
                    break;
                case ApiService.ChannelLanding:
                    path = "/rest/v1/channels?username={$username}";
                    break;
                case ApiService.ChannelSnapshot:
                    path = "/rest/v1/channels/{$channelID}/snapshot?username={$username}&game={$game}&market={$market}&timing={$timing}";
                    break;
                case ApiService.ChannelHistory:
                    path = "/rest/v1/channels/{$channelID}/history?username={$username}";
                    break;
                case ApiService.ChannelInfo:
                    path = "/rest/v1/channels/{$channelID}/info?username={$username}";
                    break;
                case ApiService.Ping:
                    path = "/rest/v1/ping?username={$username}";
                    break;
            }

            // ask for extended timing info via url
            if (m_AllowExtendedTimings == true)
            {
                path += "&extendedTiming=true";
            }

            // remove username from url if it's not supplied
            if (string.IsNullOrEmpty(m_BetfairUsername) == true)
            {
                string replace = "username={$username}";

                if (path.IndexOf("&") == -1)
                {
                    // we must also remove the '?' if username is the only param
                    replace = "?" + replace;
                    path = path.Replace(replace, string.Empty);
                }
                else
                {
                    // we must also remove the '&' if username is not the only param
                    replace = replace + "&";
                    path = path.Replace(replace, string.Empty);
                }
            }

            return _FormatUriParameters(String.Format("{0}{1}", m_BaseUrl, path), parameters);
        }

        /// <summary>
        /// Apply list of parameters to request url
        /// </summary>
        /// <param name="url">The current url</param>
        /// <param name="parameters">List of parameters</param>
        /// <returns>Formatted Url</returns>
        private string _FormatUriParameters(string url, Hashtable parameters)
        {
            string processedUrl = url;

            if (processedUrl.Length > 0)
            {
                // replace all tokens with the relevant parameter data
                string[] lines = processedUrl.Split('$');

                foreach (string splitItem in lines)
                {
                    if (splitItem.IndexOf("}") > -1)
                    {
                        string token = splitItem.Substring(0, splitItem.IndexOf("}"));
                        processedUrl = processedUrl.Replace("{$" + token + "}", parameters[token] as string);
                    }
                }
            }

            return processedUrl;
        }

        /// <summary>
        /// Get non-optional params for URL creation
        /// </summary>
        /// <returns></returns>
        private Hashtable _GetParameters()
        {
            Hashtable ht = new Hashtable();
            if (m_BetfairUsername != null)
            {
                ht.Add("username", m_BetfairUsername);
            }
            return ht;
        }

        private void _SSLCertificateOverride()
        {
            ServicePointManager.ServerCertificateValidationCallback = delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };
        }

        /// <summary>
        /// Get xml response from url
        /// </summary>
        /// <param name="url">Url to hit</param>
        /// <returns>Xml string</returns>
		private string _GetResponse(string url)
		{
			return _GetResponse(url, string.Empty);
		}

        /// <summary>
        /// Get xml response from url
        /// </summary>
        /// <param name="url">Url to hit</param>
        /// <param name="postData">Data to post</param>
        /// <returns>Xml string</returns>
        private string _GetResponse(string url, string postData)
		{
            m_RequestedUrl = url;

            if (m_OutputXml == true)
            {
                Console.WriteLine();
                Console.WriteLine(url);
                Console.WriteLine();

                if (postData != null && postData.Length != 0)
                {
                    Console.WriteLine(postData);
                    Console.WriteLine();
                }
            }

            // create request details/headers etc
            string responseData = null;
            HttpWebRequest http = _SetupWebRequest(url, postData);

            try
            {
                _StartRequestStamp();

                // fire the actual request
                using (HttpWebResponse response = http.GetResponse() as HttpWebResponse)
                {
                    _EndRequestStamp();

                    // process the response
                    responseData = _ProcessWebResponse(response, false);
                }
            }
            catch
            {
                _EndRequestStamp();
                throw;
            }

            http = null;

            if (m_OutputXml == true)
            {
                Console.WriteLine();
                Console.WriteLine(responseData);
                Console.WriteLine();
            }

            // check for error string, if error serialize an error object and throw in exception
            if (responseData.IndexOf("<error") != -1)
            {
                error err = ((error)_DeSerialize(typeof(error), responseData));
                throw new APIException(err);
            }

            return responseData;
		}

        /// <summary>
        /// Builds the web request
        /// </summary>
        /// <param name="url">Url to request</param>
        /// <param name="postData">Data to post (if any)</param>
        /// <returns>HttpWebRequest object</returns>
        private HttpWebRequest _SetupWebRequest(string url, string postData)
        {
            HttpWebRequest http = WebRequest.Create(url) as HttpWebRequest;

            http.Method = "GET";
            http.Headers.Add("Front-End-Https", "on");
            http.KeepAlive = true;
            http.CachePolicy = new RequestCachePolicy(RequestCacheLevel.BypassCache);

            // add extra specified headers
            foreach (KeyValuePair<string, string> entry in m_ExtraHeaders)
            {
                http.Headers.Add(entry.Key, entry.Value);
            }

            // setup the optional headers
            if (this.SendPassword == true && string.IsNullOrEmpty(m_BetfairPassword) == false)
            {
                http.Headers.Add(PasswordHeaderName, m_BetfairPassword);
            }

            // single sign on token, if supplied
            if (string.IsNullOrEmpty(m_SsoToken) == false)
            {
                http.Headers.Add("ssoid", m_SsoToken);
            }

            if (this.SendAgent == true)
            {
                http.Headers.Add("gamexAPIAgent", this.APIAgent);
            }

            if (this.SendAgentInstance == true)
            {
                http.Headers.Add("gamexAPIAgentInstance", Environment.MachineName);
            }

            // store post data for current request
            m_RequestXml = postData;

            // setup post details if we are posting XML
            if (postData.Length > 0)
            {
                http.Method = "POST";

                http.ContentType = "application/xml; charset=UTF-8";
                http.ContentLength = postData.Length;

                using (Stream requestStream = http.GetRequestStream())
                {
                    using (StreamWriter sr = new StreamWriter(requestStream))
                    {
                        sr.Write(postData);
                    }
                }
            }

            return http;
        }

        /// <summary>
        /// Process the response and return xml
        /// </summary>
        /// <param name="resp">Response object</param>
        /// <param name="async">If part of async request</param>
        /// <returns>Xml string</returns>
        private string _ProcessWebResponse(HttpWebResponse resp, bool async)
        {
            string responseText = string.Empty;
            using (Stream respStream = resp.GetResponseStream())
            {
                using (StreamReader sr = new StreamReader(respStream))
                {
                    responseText = sr.ReadToEnd();
                    m_ResponseXml = responseText;
                }
            }

            // set the time taken if header is present
            if (resp.Headers[ProcessTimeHeaderName] != null)
            {
                m_ServerTimeTaken = int.Parse(resp.Headers[ProcessTimeHeaderName]);

                if (async == false)
                {
                    // subtract server time from request time to get time inside network
                    m_NetworkTimeTaken = m_RequestTimeTaken - m_ServerTimeTaken;
                }
            }
            else
            {
                m_ServerTimeTaken = 0;
                m_NetworkTimeTaken = 0;
            }

            // look for extended timing info
            if (m_AllowExtendedTimings == true)
            {
                m_ExtendedTimings = new Dictionary<string, int>(5);

                // go through every header that starts X-timing
                foreach (string header in resp.Headers.AllKeys)
                {
                    if (header.IndexOf("X-timing") != -1)
                    {
                        string val = resp.Headers[header];
                        m_ExtendedTimings.Add(header, Convert.ToInt32(val));
                    }
                }
            }

            return responseText;
        }

		private System.IAsyncResult _BeginGetResponse(string url, System.AsyncCallback callback, object asyncState)
		{
            return _BeginGetResponse(url, string.Empty, callback, asyncState);
		}

		private System.IAsyncResult _BeginGetResponse(string url, string postData, System.AsyncCallback callback, object asyncState)
		{
            m_RequestedUrl = url;
			HttpWebRequest http = _SetupWebRequest(url, postData);

			// abstract the user's async state into our custom AsyncRequestState object
			AsyncRequestState state = new AsyncRequestState();
			state.UserAsyncState = asyncState;
			state.WebRequest = http;
			state.Adapter = this;
			state.Timer = new PerformanceTimer();
			state.Timer.Start();

			return http.BeginGetResponse(callback, state);
		}

		private AsyncResponseState _EndGetResponse(System.IAsyncResult asyncResult)
		{
			// get callee object
			AsyncRequestState requestState = (AsyncRequestState)asyncResult.AsyncState;

			// create a return state object
			AsyncResponseState responseState = new AsyncResponseState();

			// migrate data from request state object to response state object
			responseState.UserAsyncState = requestState.UserAsyncState;
			responseState.Adapter = (Adapter)requestState.Adapter;
			HttpWebRequest http = (HttpWebRequest)requestState.WebRequest;

			// get raw xml returned from call
			responseState.ResponsedXml = _ProcessWebResponse((HttpWebResponse)http.EndGetResponse(asyncResult), true);

			// log time taken
			requestState.Timer.Stop();
            responseState.RequestTimeTaken = requestState.Timer.MillisecondDuration;
            responseState.ServerTimeTaken = m_ServerTimeTaken;

			// update Url requested
			responseState.RequestedUrl = RequestedUrl;
			return responseState;
		}
		#endregion

        #region Timer Methods
        /// <summary>
        /// Log start of public method
        /// </summary>
        private void _StartMethodStamp()
        {
            m_OverallTimer.Start();
        }

        /// <summary>
        /// Log end of public method and get milliseconds taken
        /// </summary>
        private void _EndMethodStamp()
        {
            m_OverallTimer.Stop();
            m_OverallTimeTaken = m_OverallTimer.MillisecondDuration;
            m_SerializationTimeTaken = m_OverallTimeTaken - m_RequestTimeTaken;
        }

        /// <summary>
        /// Log start of request
        /// </summary>
        private void _StartRequestStamp()
        {
            m_RequestTimer.Start();
        }

        /// <summary>
        /// Log end of request and get milliseconds taken
        /// </summary>
        private void _EndRequestStamp()
        {
            m_RequestTimer.Stop();
            m_RequestTimeTaken = m_RequestTimer.MillisecondDuration;
        }

        /// <summary>
        /// Overall time last method call took
        /// </summary>
        public int OverallTimeTaken
        {
            get
            { 
                return m_OverallTimeTaken; 
            }
        }

        /// <summary>
        /// Request time taken
        /// </summary>
        public int RequestTimeTaken
        {
            get
            {
                return m_RequestTimeTaken; 
            }
        }

        /// <summary>
        /// Network time taken
        /// </summary>
        public int NetworkTimeTaken
        {
            get
            {
                return m_NetworkTimeTaken;
            }
        }

        /// <summary>
        /// Time to serialize/deserialize data
        /// </summary>
        public int SerializationTimeTaken
        {
            get
            {
                return m_SerializationTimeTaken;
            }
        }

        /// <summary>
        /// The server time taken to service the request
        /// </summary>
        public int ServerTimeTaken
        {
            get
            {
                return m_ServerTimeTaken;
            }
        }
        #endregion

        #region Public Api Access Methods
        /// <summary>
        /// Get API start page
        /// </summary>
        /// <returns></returns>
		public api GetLanding() 
		{
            _StartMethodStamp();

			string response = _GetResponse(_GetTargetUri(ApiService.V1Landing, _GetParameters()));
            api obj = _DeSerialize(typeof(api), response) as api;

            _EndMethodStamp();

            return obj;
		}

        /// <summary>
        /// Account landing page
        /// </summary>
        /// <returns></returns>
		public accountLanding GetAccountLanding()
		{
            _StartMethodStamp();

            string response = _GetResponse(_GetTargetUri(ApiService.AccountLanding, _GetParameters()));
            accountLanding obj = _DeSerialize(typeof(accountLanding), response) as accountLanding;

            _EndMethodStamp();

            return obj;
		}

        /// <summary>
        /// Gets account snapshot
        /// </summary>
        /// <returns></returns>
		public accountSnapshot GetAccountSnapshot()
		{
            _StartMethodStamp();

            string response = _GetResponse(_GetTargetUri(ApiService.AccountSnapshot, _GetParameters()));
            accountSnapshot obj = _DeSerialize(typeof(accountSnapshot), response) as accountSnapshot;

            _EndMethodStamp();

            return obj;
		}

        /// <summary>
        /// Betfair account snapshot
        /// </summary>
        /// <returns></returns>
        public betfairAvailableBalance GetAccountBetfairSnapshot()
        {
            _StartMethodStamp();

            string response = _GetResponse(_GetTargetUri(ApiService.AccountBetfairSnapshot, _GetParameters()));
            betfairAvailableBalance obj = _DeSerialize(typeof(betfairAvailableBalance), response) as betfairAvailableBalance;

            _EndMethodStamp();

            return obj;
        }

		/// <summary>
		/// Get account statement
		/// </summary>
		/// <returns></returns>
		public accountStatement GetAccountStatement()
		{
            return GetAccountStatement(_GetTargetUri(ApiService.AccountStatement, _GetParameters()));
		}

        /// <summary>
        /// Get account statement
        /// </summary>
        /// <param name="Url"></param>
        /// <returns></returns>
		public accountStatement GetAccountStatement(string Url)
		{
            _StartMethodStamp();

            string response = _GetResponse(Url);
            accountStatement obj = _DeSerialize(typeof(accountStatement), response) as accountStatement;

            _EndMethodStamp();

            return obj;
		}

		/// <summary>
		/// Transfer money in and out of games
		/// </summary>
		/// <param name="amount"></param>
		/// <param name="currency"></param>
		/// <returns></returns>
		public responseTransferOrder SetAccountTransferOrder(double amount, string currency)
		{
            _StartMethodStamp();

            string response = _GetResponse(_GetTargetUri(ApiService.AccountTransferOrder, _GetParameters()), _Serialize(typeof(postTransferOrder), _GetTransferOrder(amount, currency)));
            responseTransferOrder obj = _DeSerialize(typeof(responseTransferOrder), response) as responseTransferOrder;

            _EndMethodStamp();

            return obj;
		}

        private postTransferOrder _GetTransferOrder(double amount, string currency)
        {
            postTransferOrder transferOrder = new postTransferOrder();
            transferOrder.amount = new postTransferOrderAmount();
            transferOrder.amount.action = balanceActionTypeEnum.TRANSFER;
            transferOrder.amount.Value = amount;
            transferOrder.amount.currency = currency;
            return transferOrder;
        }

        /// <summary>
        /// Bet landing page
        /// </summary>
        /// <returns></returns>
		public betLanding GetBetLanding()
		{
            _StartMethodStamp();

            string response = _GetResponse(_GetTargetUri(ApiService.BetLanding, _GetParameters()));
            betLanding obj = _DeSerialize(typeof(betLanding), response) as betLanding;

            _EndMethodStamp();

            return obj;
		}

        /// <summary>
        /// Bet snapshot
        /// </summary>
        /// <param name="Url"></param>
        /// <returns></returns>
		public betSnapshot GetBetSnapshot(string Url) 
		{
            _StartMethodStamp();

            string response = _GetResponse(Url);
            betSnapshot obj = _DeSerialize(typeof(betSnapshot), response) as betSnapshot;

            _EndMethodStamp();

            return obj;
		}

        /// <summary>
        /// Bet snapshot
        /// </summary>
        /// <param name="betStatus"></param>
        /// <param name="optionalChannelID"></param>
        /// <param name="orderBetsBy"></param>
        /// <returns></returns>
        public betSnapshot GetBetSnapshot(BetSnapshotBetStatus betStatus, long optionalChannelID, BetSnapshotOrderBy orderBetsBy)
        {
            return GetBetSnapshot(betStatus, optionalChannelID, orderBetsBy, string.Empty);
        }

        /// <summary>
        /// Bet snapshot
        /// </summary>
        /// <param name="betStatus"></param>
        /// <param name="optionalChannelID"></param>
        /// <param name="orderBetsBy"></param>
        /// <param name="optionalSelectionsType"></param>
        /// <returns></returns>
        public betSnapshot GetBetSnapshot(BetSnapshotBetStatus betStatus, long optionalChannelID, BetSnapshotOrderBy orderBetsBy, string optionalSelectionsType)
		{
            return GetBetSnapshot(_GetBetSnapshotUri(betStatus, orderBetsBy, optionalChannelID, optionalSelectionsType));
		}

        private string _GetBetSnapshotUri(BetSnapshotBetStatus betStatus, BetSnapshotOrderBy orderBetsBy, long optionalChannelID, string selectionsType)
        {
            Hashtable parameters = _GetParameters();
            parameters.Add("betStatus", betStatus.ToString());
            parameters.Add("orderBy", orderBetsBy.ToString());

            string uri = _GetTargetUri(ApiService.BetSnapshot, parameters);

            if (optionalChannelID != -1)
            {
                uri = String.Format("{0}&channelId={1}", uri, optionalChannelID);
            }

            if (string.IsNullOrEmpty(selectionsType) == false)
            {
                uri = String.Format("{0}&selectionsType={1}", uri, selectionsType);
            }

            return uri;
        }

		/// <summary>
		/// Get bet history
		/// </summary>
		/// <param name="url"></param>
		/// <returns></returns>
		public betHistory GetBetHistory(string url)
		{
            _StartMethodStamp();

            string response = _GetResponse(url);
            betHistory obj = _DeSerialize(typeof(betHistory), response) as betHistory;

            _EndMethodStamp();

            return obj;
		}

        /// <summary>
        /// Get bet history
        /// </summary>
        /// <param name="betStatus"></param>
        /// <param name="optionalStartDate"></param>
        /// <param name="optionalEndDate"></param>
        /// <returns></returns>
		public betHistory GetBetHistory(BetHistoryBetStatus betStatus, DateTime optionalStartDate, DateTime optionalEndDate)
		{
            return GetBetHistory(_GetBetHistoryUri(betStatus, optionalStartDate, optionalEndDate));
		}

        private string _GetBetHistoryUri(BetHistoryBetStatus betStatus, DateTime optionalStartDate, DateTime optionalEndDate)
        {
            Hashtable parameters = _GetParameters();
            parameters.Add("betStatus", betStatus.ToString());

            string queryAddOn = string.Empty;
            if (optionalStartDate != DateTime.MinValue)
            {
                queryAddOn = string.Format("&startDate={0}", HttpUtility.UrlEncode(string.Format("{0:yyyy}-{0:MM}-{0:dd}", optionalStartDate)));
            }

            if (optionalEndDate != DateTime.MinValue)
            {
                queryAddOn = string.Format("{0}&endDate={1}", queryAddOn, HttpUtility.UrlEncode(string.Format("{0:yyyy}-{0:MM}-{0:dd}", optionalEndDate)));
            }

            return string.Format("{0}{1}", _GetTargetUri(ApiService.BetHistory, parameters), queryAddOn);
        }

        /// <summary>
        /// Post bets to games
        /// </summary>
        /// <param name="betOrder"></param>
        /// <returns></returns>
		public responseBetOrder SetBetOrder(postBetOrder betOrder) 
		{
            _StartMethodStamp();

            string response = _GetResponse(_GetTargetUri(ApiService.BetOrder, _GetParameters()), _Serialize(typeof(postBetOrder), betOrder));
            responseBetOrder obj = _DeSerialize(typeof(responseBetOrder), response) as responseBetOrder;

            _EndMethodStamp();

            return obj;
		}

		/// <summary>
		/// Get channel landing
		/// </summary>
		/// <returns></returns>
		public channelLanding GetChannelLanding()
		{
            _StartMethodStamp();

            string response = _GetResponse(_GetTargetUri(ApiService.ChannelLanding, _GetParameters()));
            channelLanding obj = _DeSerialize(typeof(channelLanding), response) as channelLanding;

            _EndMethodStamp();

            return obj;
		}

		/// <summary>
		/// Get channel snapshot
		/// </summary>
		/// <param name="Url"></param>
		/// <returns></returns>
		public channelSnapshot GetChannelSnapshot(string Url)
		{
            _StartMethodStamp();

            string response = _GetResponse(Url);
            channelSnapshot obj = _DeSerialize(typeof(channelSnapshot), response) as channelSnapshot;

            _EndMethodStamp();

            return obj;
		}

        /// <summary>
        /// Get channel snapshot
        /// </summary>
        /// <param name="channelID"></param>
        /// <returns></returns>
		public channelSnapshot GetChannelSnapshot(long channelID)
		{
			return GetChannelSnapshot(channelID, true, true, true, string.Empty);
		}

        /// <summary>
        /// Get channel snapshot
        /// </summary>
        /// <param name="channelID"></param>
        /// <param name="gameData"></param>
        /// <param name="marketData"></param>
        /// <param name="timingData"></param>
        /// <param name="selectionsType"></param>
        /// <returns></returns>
        public channelSnapshot GetChannelSnapshot(long channelID, bool gameData, bool marketData, bool timingData, string selectionsType)
        {
            Hashtable parameters = _GetParameters();
            parameters.Add("channelID", channelID.ToString());
            parameters.Add("game", gameData.ToString().ToLower());
            parameters.Add("market", marketData.ToString().ToLower());
            parameters.Add("timing", timingData.ToString().ToLower());

            string uri = _GetTargetUri(ApiService.ChannelSnapshot, parameters);
            if (string.IsNullOrEmpty(selectionsType) == false)
            {
                uri = String.Format("{0}&selectionsType={1}", uri, selectionsType);
            }

            return GetChannelSnapshot(uri);
        }

        /// <summary>
        /// Get channel history
        /// </summary>
        /// <param name="Url"></param>
        /// <returns></returns>
		public channelHistory GetChannelHistory(string Url)
		{
            _StartMethodStamp();

            string response = _GetResponse(Url);
            channelHistory obj = _DeSerialize(typeof(channelHistory), response) as channelHistory;

            _EndMethodStamp();

            return obj;
		}

        /// <summary>
        /// Get channel history
        /// </summary>
        /// <param name="channelID"></param>
        /// <param name="optionalMarketID"></param>
        /// <returns></returns>
		public channelHistory GetChannelHistory(int channelID, int optionalMarketID)
		{
            return GetChannelHistory(_GetChannelHistoryUri(channelID, optionalMarketID));
		}

        private string _GetChannelHistoryUri(int channelID, int optionalMarketID)
        {
            Hashtable parameters = _GetParameters();
            parameters.Add("channelID", channelID.ToString());

            string url = _GetTargetUri(ApiService.ChannelHistory, parameters);
            if (optionalMarketID != -1)
            {
                url = String.Format("{0}&marketId={1}", url, optionalMarketID);
            }

            return url;
        }

		/// <summary>
		/// Get channel details
		/// </summary>
		/// <param name="Url"></param>
		/// <returns></returns>
		public channelInfo GetChannelInfo(string Url)
		{
            _StartMethodStamp();

            string response = _GetResponse(Url);
            channelInfo obj = _DeSerialize(typeof(channelInfo), response) as channelInfo;

            _EndMethodStamp();

            return obj;
		}

        /// <summary>
        /// Get channel details
        /// </summary>
        /// <param name="channelID"></param>
        /// <returns></returns>
		public channelInfo GetChannelInfo(int channelID)
		{
			Hashtable parameters = _GetParameters();
			parameters.Add("channelID", channelID.ToString());
			return GetChannelInfo(_GetTargetUri(ApiService.ChannelInfo, parameters));
		}

		/// <summary>
		/// Ping games api
		/// </summary>
		/// <returns></returns>
		public ping Ping()
		{
            _StartMethodStamp();

            string response = _GetResponse(_GetTargetUri(ApiService.Ping, _GetParameters()));
            ping obj = _DeSerialize(typeof(ping), response) as ping;

            _EndMethodStamp();

            return obj;
		}
		#endregion

        #region Async Requests
        /// <summary>
        /// Async get landing page
        /// </summary>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetLanding(System.AsyncCallback callback, object asyncState)
        {
            return _BeginGetResponse(_GetTargetUri(ApiService.V1Landing, _GetParameters()), callback, asyncState);
        }

        /// <summary>
        /// Async get landing page
        /// </summary>
        /// <param name="asyncResult"></param>
        /// <returns></returns>
        public AsyncResponseState EndGetLanding(System.IAsyncResult asyncResult)
        {
            AsyncResponseState responseState = _EndGetResponse(asyncResult);
            responseState.ReturnObject = _DeSerialize(typeof(api), responseState.ResponsedXml);
            return responseState;
        }

        /// <summary>
        /// Async get account landing
        /// </summary>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetAccountLanding(System.AsyncCallback callback, object asyncState)
        {
            return _BeginGetResponse(_GetTargetUri(ApiService.AccountLanding, _GetParameters()), callback, asyncState);
        }

        /// <summary>
        /// Async get account landing
        /// </summary>
        /// <param name="asyncResult"></param>
        /// <returns></returns>
        public AsyncResponseState EndGetAccountLanding(System.IAsyncResult asyncResult)
        {
            AsyncResponseState responseState = _EndGetResponse(asyncResult);
            responseState.ReturnObject = _DeSerialize(typeof(accountLanding), responseState.ResponsedXml);
            return responseState;
        }

        /// <summary>
        /// Async get account snapshot
        /// </summary>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetAccountSnapshot(System.AsyncCallback callback, object asyncState)
        {
            return _BeginGetResponse(_GetTargetUri(ApiService.AccountSnapshot, _GetParameters()), callback, asyncState);
        }

        /// <summary>
        /// Async get account snapshot
        /// </summary>
        /// <param name="asyncResult"></param>
        /// <returns></returns>
        public AsyncResponseState EndGetAccountSnapshot(System.IAsyncResult asyncResult)
        {
            AsyncResponseState responseState = _EndGetResponse(asyncResult);
            responseState.ReturnObject = _DeSerialize(typeof(accountSnapshot), responseState.ResponsedXml);
            return responseState;
        }

        /// <summary>
        /// Async get betfair account snapshot
        /// </summary>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetAccountBetfairSnapshot(System.AsyncCallback callback, object asyncState)
        {
            return _BeginGetResponse(_GetTargetUri(ApiService.AccountBetfairSnapshot, _GetParameters()), callback, asyncState);
        }

        /// <summary>
        /// Async get betfair account snapshot
        /// </summary>
        /// <param name="asyncResult"></param>
        /// <returns></returns>
        public AsyncResponseState EndGetAccountBetfairSnapshot(System.IAsyncResult asyncResult)
        {
            AsyncResponseState responseState = _EndGetResponse(asyncResult);
            responseState.ReturnObject = _DeSerialize(typeof(betfairAvailableBalance), responseState.ResponsedXml);
            return responseState;
        }

        /// <summary>
        /// Async get account snapshot
        /// </summary>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetAccountStatement(System.AsyncCallback callback, object asyncState)
        {
            return BeginGetAccountStatement(_GetTargetUri(ApiService.AccountStatement, _GetParameters()), callback, asyncState);
        }

        /// <summary>
        /// Async get account snapshot
        /// </summary>
        /// <param name="Url"></param>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetAccountStatement(string Url, System.AsyncCallback callback, object asyncState)
        {
            return _BeginGetResponse(Url, callback, asyncState);
        }

        /// <summary>
        /// Async get account snapshot
        /// </summary>
        /// <param name="asyncResult"></param>
        /// <returns></returns>
        public AsyncResponseState EndGetAccountStatement(System.IAsyncResult asyncResult)
        {
            AsyncResponseState responseState = _EndGetResponse(asyncResult);
            responseState.ReturnObject = _DeSerialize(typeof(accountStatement), responseState.ResponsedXml);
            return responseState;
        }

        /// <summary>
        /// Async transfer funds
        /// </summary>
        /// <param name="amount"></param>
        /// <param name="currency"></param>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginSetAccountTransferOrder(double amount, string currency, System.AsyncCallback callback, object asyncState)
        {
            return _BeginGetResponse(_GetTargetUri(ApiService.AccountTransferOrder, _GetParameters()), _Serialize(typeof(postTransferOrder), _GetTransferOrder(amount, currency)), callback, asyncState);
        }

        /// <summary>
        /// Async transfer funds
        /// </summary>
        /// <param name="asyncResult"></param>
        /// <returns></returns>
        public AsyncResponseState EndSetAccountTransferOrder(System.IAsyncResult asyncResult)
        {
            AsyncResponseState responseState = _EndGetResponse(asyncResult);
            responseState.ReturnObject = _DeSerialize(typeof(responseTransferOrder), responseState.ResponsedXml);
            return responseState;
        }

        /// <summary>
        /// Async get bet landing page
        /// </summary>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetBetLanding(System.AsyncCallback callback, object asyncState)
        {
            return _BeginGetResponse(_GetTargetUri(ApiService.BetLanding, _GetParameters()), callback, asyncState);
        }

        /// <summary>
        /// Async get bet landing page
        /// </summary>
        /// <param name="asyncResult"></param>
        /// <returns></returns>
        public AsyncResponseState EndGetBetLanding(System.IAsyncResult asyncResult)
        {
            AsyncResponseState responseState = _EndGetResponse(asyncResult);
            responseState.ReturnObject = _DeSerialize(typeof(betLanding), responseState.ResponsedXml);
            return responseState;
        }

        /// <summary>
        /// Async get bet snapshot
        /// </summary>
        /// <param name="betStatus"></param>
        /// <param name="optionalChannelID"></param>
        /// <param name="orderBetsBy"></param>
        /// <param name="optionalSelectionsType"></param>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetBetSnapshot(BetSnapshotBetStatus betStatus, int optionalChannelID, BetSnapshotOrderBy orderBetsBy, string optionalSelectionsType, System.AsyncCallback callback, object asyncState)
        {
            return BeginGetBetSnapshot(_GetBetSnapshotUri(betStatus, orderBetsBy, optionalChannelID, optionalSelectionsType), callback, asyncState);
        }

        /// <summary>
        /// Async get bet snapshot
        /// </summary>
        /// <param name="Url"></param>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetBetSnapshot(string Url, System.AsyncCallback callback, object asyncState)
        {
            return _BeginGetResponse(Url, callback, asyncState);
        }

        /// <summary>
        /// Async get bet snapshot
        /// </summary>
        /// <param name="asyncResult"></param>
        /// <returns></returns>
        public AsyncResponseState EndGetBetSnapshot(System.IAsyncResult asyncResult)
        {
            AsyncResponseState responseState = _EndGetResponse(asyncResult);
            responseState.ReturnObject = _DeSerialize(typeof(betSnapshot), responseState.ResponsedXml);
            return responseState;
        }

        /// <summary>
        /// Async get bet history
        /// </summary>
        /// <param name="betStatus"></param>
        /// <param name="optionalStartDate"></param>
        /// <param name="optionalEndDate"></param>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetBetHistory(BetHistoryBetStatus betStatus, DateTime optionalStartDate, DateTime optionalEndDate, System.AsyncCallback callback, object asyncState)
        {
            return BeginGetBetHistory(_GetBetHistoryUri(betStatus, optionalStartDate, optionalEndDate), callback, asyncState);
        }

        /// <summary>
        /// Async get bet history
        /// </summary>
        /// <param name="Url"></param>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetBetHistory(string Url, System.AsyncCallback callback, object asyncState)
        {
            return _BeginGetResponse(Url, callback, asyncState);
        }

        /// <summary>
        /// Async get bet history
        /// </summary>
        /// <param name="asyncResult"></param>
        /// <returns></returns>
        public AsyncResponseState EndGetBetHistory(System.IAsyncResult asyncResult)
        {
            AsyncResponseState responseState = _EndGetResponse(asyncResult);
            responseState.ReturnObject = _DeSerialize(typeof(betHistory), responseState.ResponsedXml);
            return responseState;
        }

        /// <summary>
        /// Async bet placement
        /// </summary>
        /// <param name="betOrder"></param>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginSetBetOrder(postBetOrder betOrder, System.AsyncCallback callback, object asyncState)
        {
            return _BeginGetResponse(_GetTargetUri(ApiService.BetOrder, _GetParameters()), _Serialize(typeof(postBetOrder), betOrder), callback, asyncState);
        }

        /// <summary>
        /// Async bet placement
        /// </summary>
        /// <param name="asyncResult"></param>
        /// <returns></returns>
        public AsyncResponseState EndSetBetOrder(System.IAsyncResult asyncResult)
        {
            AsyncResponseState responseState = _EndGetResponse(asyncResult);
            responseState.ReturnObject = _DeSerialize(typeof(responseBetOrder), responseState.ResponsedXml);
            return responseState;
        }

        /// <summary>
        /// Async channel landing
        /// </summary>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetChannelLanding(System.AsyncCallback callback, object asyncState)
        {
            return _BeginGetResponse(_GetTargetUri(ApiService.ChannelLanding, _GetParameters()), callback, asyncState);
        }

        /// <summary>
        /// Async channel landing
        /// </summary>
        /// <param name="asyncResult"></param>
        /// <returns></returns>
        public AsyncResponseState EndGetChannelLanding(System.IAsyncResult asyncResult)
        {
            AsyncResponseState responseState = _EndGetResponse(asyncResult);
            responseState.ReturnObject = _DeSerialize(typeof(channelLanding), responseState.ResponsedXml);
            return responseState;
        }

        /// <summary>
        /// Async channel snapshot
        /// </summary>
        /// <param name="channelID"></param>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetChannelSnapshot(int channelID, System.AsyncCallback callback, object asyncState)
        {
            Hashtable parameters = _GetParameters();
            parameters.Add("channelID", channelID.ToString());
            return BeginGetChannelSnapshot(_GetTargetUri(ApiService.ChannelSnapshot, parameters), callback, asyncState);
        }

        /// <summary>
        /// Async channel snapshot
        /// </summary>
        /// <param name="Url"></param>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetChannelSnapshot(string Url, System.AsyncCallback callback, object asyncState)
        {
            return _BeginGetResponse(Url, callback, asyncState);
        }

        /// <summary>
        /// Async channel snapshot
        /// </summary>
        /// <param name="asyncResult"></param>
        /// <returns></returns>
        public AsyncResponseState EndGetChannelSnapshot(System.IAsyncResult asyncResult)
        {
            AsyncResponseState responseState = _EndGetResponse(asyncResult);
            responseState.ReturnObject = _DeSerialize(typeof(channelSnapshot), responseState.ResponsedXml);
            return responseState;
        }

        /// <summary>
        /// Async channel history
        /// </summary>
        /// <param name="channelID"></param>
        /// <param name="optionalMarketID"></param>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetChannelHistory(int channelID, int optionalMarketID, System.AsyncCallback callback, object asyncState)
        {
            return BeginGetChannelHistory(_GetChannelHistoryUri(channelID, optionalMarketID), callback, asyncState);
        }

        /// <summary>
        /// Async channel history
        /// </summary>
        /// <param name="Url"></param>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetChannelHistory(string Url, System.AsyncCallback callback, object asyncState)
        {
            return _BeginGetResponse(Url, callback, asyncState);
        }

        /// <summary>
        /// Async channel history
        /// </summary>
        /// <param name="asyncResult"></param>
        /// <returns></returns>
        public AsyncResponseState EndGetChannelHistory(System.IAsyncResult asyncResult)
        {
            AsyncResponseState responseState = _EndGetResponse(asyncResult);
            responseState.ReturnObject = _DeSerialize(typeof(channelHistory), responseState.ResponsedXml);
            return responseState;
        }

        /// <summary>
        /// Async get channel info
        /// </summary>
        /// <param name="channelID"></param>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetChannelInfo(int channelID, System.AsyncCallback callback, object asyncState)
        {
            Hashtable parameters = _GetParameters();
            parameters.Add("channelID", channelID.ToString());
            return BeginGetChannelInfo(_GetTargetUri(ApiService.ChannelInfo, parameters), callback, asyncState);
        }

        /// <summary>
        /// Async get channel info
        /// </summary>
        /// <param name="Url"></param>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetChannelInfo(string Url, System.AsyncCallback callback, object asyncState)
        {
            return _BeginGetResponse(Url, callback, asyncState);
        }

        /// <summary>
        /// Async get channel info
        /// </summary>
        /// <param name="asyncResult"></param>
        /// <returns></returns>
        public AsyncResponseState EndGetChannelInfo(System.IAsyncResult asyncResult)
        {
            AsyncResponseState responseState = _EndGetResponse(asyncResult);
            responseState.ReturnObject = _DeSerialize(typeof(channelInfo), responseState.ResponsedXml);
            return responseState;
        }

        /// <summary>
        /// Async ping
        /// </summary>
        /// <param name="callback"></param>
        /// <param name="asyncState"></param>
        /// <returns></returns>
        public System.IAsyncResult BeginGetPing(System.AsyncCallback callback, object asyncState)
        {
            return _BeginGetResponse(_GetTargetUri(ApiService.Ping, _GetParameters()), callback, asyncState);
        }

        /// <summary>
        /// Async ping
        /// </summary>
        /// <param name="asyncResult"></param>
        /// <returns></returns>
        public AsyncResponseState EndGetPing(System.IAsyncResult asyncResult)
        {
            AsyncResponseState responseState = _EndGetResponse(asyncResult);
            responseState.ReturnObject = _DeSerialize(typeof(ping), responseState.ResponsedXml);
            return responseState;
        }
        #endregion
    }
}
