using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Rest.Net
{
    public class RouteArgumentConverter
    {
        public static T Convert<T>(string input)
        {
            var typeCode = Type.GetTypeCode(typeof(T));

            if (typeCode == TypeCode.String)
            {
                return (dynamic)input;
            }
            else if (typeCode == TypeCode.Object)
            {
                var castOperator = typeof(T).GetMethod("op_Explicit", new[] { typeof(string) });

                if (castOperator == null)
                    return default(T);

                return (T)castOperator.Invoke(null, new[] { input });
            }
            else if (typeCode == TypeCode.Double)
            {
                double.TryParse(input, out double result);
                return (dynamic)result;
            }
            else if (typeCode == TypeCode.Single)
            {
                float.TryParse(input, out float result);
                return (dynamic)result;
            }
            else if (typeCode == TypeCode.Decimal)
            {
                decimal.TryParse(input, out decimal result);
                return (dynamic)result;
            }
            else if (typeCode == TypeCode.Int64)
            {
                long.TryParse(input, out long result);
                return (dynamic)result;
            }
            else if (typeCode == TypeCode.Int32)
            {
                int.TryParse(input, out int result);
                return (dynamic)result;
            }
            else if (typeCode == TypeCode.Int16)
            {
                short.TryParse(input, out short result);
                return (dynamic)result;
            }
            else if (typeCode == TypeCode.SByte)
            {
                sbyte.TryParse(input, out sbyte result);
                return (dynamic)result;
            }
            else if (typeCode == TypeCode.UInt64)
            {
                ulong.TryParse(input, out ulong result);
                return (dynamic)result;
            }
            else if (typeCode == TypeCode.UInt32)
            {
                uint.TryParse(input, out uint result);
                return (dynamic)result;
            }
            else if (typeCode == TypeCode.UInt16)
            {
                ushort.TryParse(input, out ushort result);
                return (dynamic)result;
            }
            else if (typeCode == TypeCode.Byte)
            {
                byte.TryParse(input, out byte result);
                return (dynamic)result;
            }
            else if (typeCode == TypeCode.Boolean)
            {
                if (input == "f" || input == "0" || input == "F")
                    return (dynamic)false;

                bool.TryParse(input, out bool result);
                return ((dynamic)result);
            }
            else if (typeCode == TypeCode.DateTime)
            {
                DateTime.TryParse(input, out DateTime result);
                return ((dynamic)result);
            }
            else if (typeCode == TypeCode.Char)
            {
                char.TryParse(input, out char result);
                return ((dynamic)result);
            }

            return default(T);
        }
    }
}