using System;
using System.IO;
using System.Reflection;
using System.Text;
using System.Web;

namespace EasyDevCore.Remote.HttpAccess
{
    /// <summary>
    /// ISerializer implementation that converts an object representing name/value pairs to a URL-encoded string.
    /// Default serializer used in calls to PostUrlEncodedAsync, etc. 
    /// </summary>
    public class UrlEncodedSerializer : ISerializer
    {
        /// <summary>
        /// Serializes the specified object.
        /// </summary>
        /// <param name="obj">The object.</param>
        public string Serialize(object obj)
        {
            if (obj == null)
                return null;

            StringBuilder sb = new StringBuilder();
            PropertyInfo[] properties = obj.GetType().GetProperties();
            foreach (PropertyInfo p in properties)
            {
                object value = p.GetValue(obj, null);
                string stringValue = value == null ? string.Empty : value.ToString();
                string objectName = HttpUtility.UrlEncode(p.Name);
                if (stringValue.Length > 0)
                {
                    stringValue = HttpUtility.UrlEncode(stringValue);
                    objectName = HttpUtility.UrlEncode(objectName);
                    if (sb.Length > 0)
                        sb.Append("&");
                    sb.Append(objectName).Append("=").Append(stringValue);
                }
            }
            return sb.ToString();
        }

        /// <summary>
        /// Serializes the specified object.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj">The object.</param>
        /// <returns></returns>
        public string Serialize<T>(T obj)
        {
            if (obj == null)
                return null;
            return Serialize(obj);
        }

        /// <summary>
        /// Deserializes the specified s.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="s">The s.</param>
        /// <exception cref="NotImplementedException">Deserializing to UrlEncoded not supported.</exception>
        public T Deserialize<T>(string s)
        {
            throw new NotImplementedException("Deserializing to UrlEncoded is not supported.");
        }

        /// <summary>
        /// Deserializes the specified stream.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="stream">The stream.</param>
        /// <exception cref="NotImplementedException">Deserializing to UrlEncoded not supported.</exception>
        public T Deserialize<T>(Stream stream)
        {
            throw new NotImplementedException("Deserializing to UrlEncoded is not supported.");
        }

        /// <summary>
        /// Deserializes the asynchronous.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="stream">The stream.</param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public Task<T> DeserializeAsync<T>(Stream stream)
        {
            throw new NotImplementedException();
        }
    }
}
