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

namespace Rest.Net
{
    public class Route
    {
        public string Method;

        public string Syntax;

        private Func<HttpListenerRequest, HttpListenerResponse, HttpListenerResponse> Target;

        public bool CloseResponse = true;

        internal Route() { }

        public Route(string method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, HttpListenerResponse> target, bool closeResponse = true)
        {
            this.Method = method;
            this.Syntax = syntax;
            this.Target = target;
            this.CloseResponse = closeResponse;
        }

        public Route(HttpRequestMethod method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, HttpListenerResponse> target, bool closeResponse = true)
            : this(method.ToString(), syntax, target, closeResponse) { }

        public virtual void Invoke(HttpListenerRequest request, HttpListenerResponse response, params string[] arguments)
        {
            this.Target.Invoke(request, response);
        }
    }

    public class Route<T1> : Route
    {
        private Func<HttpListenerRequest, HttpListenerResponse, T1, HttpListenerResponse> Target;

        public Route(string method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, T1, HttpListenerResponse> target, bool closeResponse = true)
        {
            this.Method = method;
            this.Syntax = syntax;
            this.Target = target;
            this.CloseResponse = closeResponse;
        }

        public Route(HttpRequestMethod method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, T1, HttpListenerResponse> target, bool closeResponse = true)
            : this(method.ToString(), syntax, target, closeResponse) { }

        public override void Invoke(HttpListenerRequest request, HttpListenerResponse response, params string[] arguments)
        {
            this.Target.DynamicInvoke(request, response, RouteArgumentConverter.Convert<T1>(arguments[0]));
        }
    }

    public class Route<T1, T2> : Route
    {
        private Func<HttpListenerRequest, HttpListenerResponse, T1, T2, HttpListenerResponse> Target;

        public Route(string method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, T1, T2, HttpListenerResponse> target, bool closeResponse = true)
        {
            this.Method = method;
            this.Syntax = syntax;
            this.Target = target;
            this.CloseResponse = closeResponse;
        }

        public Route(HttpRequestMethod method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, T1, T2, HttpListenerResponse> target, bool closeResponse = true)
            : this(method.ToString(), syntax, target, closeResponse) { }

        public override void Invoke(HttpListenerRequest request, HttpListenerResponse response, params string[] arguments)
        {
            this.Target.DynamicInvoke(
                request,
                response,
                RouteArgumentConverter.Convert<T1>(arguments[0]),
                RouteArgumentConverter.Convert<T2>(arguments[1])
            ); ;
        }
    }

    public class Route<T1, T2, T3> : Route
    {
        private Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, HttpListenerResponse> Target;

        public Route(string method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, HttpListenerResponse> target, bool closeResponse = true)
        {
            this.Method = method;
            this.Syntax = syntax;
            this.Target = target;
            this.CloseResponse = closeResponse;
        }

        public Route(HttpRequestMethod method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, HttpListenerResponse> target, bool closeResponse = true)
            : this(method.ToString(), syntax, target, closeResponse) { }

        public override void Invoke(HttpListenerRequest request, HttpListenerResponse response, params string[] arguments)
        {
            this.Target.DynamicInvoke(
                request,
                response,
                RouteArgumentConverter.Convert<T1>(arguments[0]),
                RouteArgumentConverter.Convert<T2>(arguments[1]),
                RouteArgumentConverter.Convert<T3>(arguments[2])
            );
        }
    }

    public class Route<T1, T2, T3, T4> : Route
    {
        private Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, T4, HttpListenerResponse> Target;

        public Route(string method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, T4, HttpListenerResponse> target, bool closeResponse = true)
        {
            this.Method = method;
            this.Syntax = syntax;
            this.Target = target;
            this.CloseResponse = closeResponse;
        }

        public Route(HttpRequestMethod method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, T4, HttpListenerResponse> target, bool closeResponse = true)
            : this(method.ToString(), syntax, target, closeResponse) { }

        public override void Invoke(HttpListenerRequest request, HttpListenerResponse response, params string[] arguments)
        {
            this.Target.DynamicInvoke(
                request,
                response,
                RouteArgumentConverter.Convert<T1>(arguments[0]),
                RouteArgumentConverter.Convert<T2>(arguments[1]),
                RouteArgumentConverter.Convert<T3>(arguments[2]),
                RouteArgumentConverter.Convert<T4>(arguments[3])
            );
        }
    }

    public class Route<T1, T2, T3, T4, T5> : Route
    {
        private Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, T4, T5, HttpListenerResponse> Target;

        public Route(string method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, T4, T5, HttpListenerResponse> target, bool closeResponse = true)
        {
            this.Method = method;
            this.Syntax = syntax;
            this.Target = target;
            this.CloseResponse = closeResponse;
        }

        public Route(HttpRequestMethod method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, T4, T5, HttpListenerResponse> target, bool closeResponse = true)
            : this(method.ToString(), syntax, target, closeResponse) { }

        public override void Invoke(HttpListenerRequest request, HttpListenerResponse response, params string[] arguments)
        {
            this.Target.DynamicInvoke(
                request,
                response,
                RouteArgumentConverter.Convert<T1>(arguments[0]),
                RouteArgumentConverter.Convert<T2>(arguments[1]),
                RouteArgumentConverter.Convert<T3>(arguments[2]),
                RouteArgumentConverter.Convert<T4>(arguments[3]),
                RouteArgumentConverter.Convert<T4>(arguments[4])
            );
        }
    }

    public class Route<T1, T2, T3, T4, T5, T6> : Route
    {
        private Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, T4, T5, T6, HttpListenerResponse> Target;

        public Route(string method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, T4, T5, T6, HttpListenerResponse> target, bool closeResponse = true)
        {
            this.Method = method;
            this.Syntax = syntax;
            this.Target = target;
            this.CloseResponse = closeResponse;
        }

        public Route(HttpRequestMethod method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, T4, T5, T6, HttpListenerResponse> target, bool closeResponse = true)
            : this(method.ToString(), syntax, target, closeResponse) { }

        public override void Invoke(HttpListenerRequest request, HttpListenerResponse response, params string[] arguments)
        {
            this.Target.DynamicInvoke(
                request,
                response,
                RouteArgumentConverter.Convert<T1>(arguments[0]),
                RouteArgumentConverter.Convert<T2>(arguments[1]),
                RouteArgumentConverter.Convert<T3>(arguments[2]),
                RouteArgumentConverter.Convert<T4>(arguments[3]),
                RouteArgumentConverter.Convert<T4>(arguments[4]),
                RouteArgumentConverter.Convert<T4>(arguments[5])
            );
        }
    }

    public class Route<T1, T2, T3, T4, T5, T6, T7> : Route
    {
        private Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, T4, T5, T6, T7, HttpListenerResponse> Target;

        public Route(string method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, T4, T5, T6, T7, HttpListenerResponse> target, bool closeResponse = true)
        {
            this.Method = method;
            this.Syntax = syntax;
            this.Target = target;
            this.CloseResponse = closeResponse;
        }

        public Route(HttpRequestMethod method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, T4, T5, T6, T7, HttpListenerResponse> target, bool closeResponse = true)
            : this(method.ToString(), syntax, target, closeResponse) { }

        public override void Invoke(HttpListenerRequest request, HttpListenerResponse response, params string[] arguments)
        {
            this.Target.DynamicInvoke(
                request,
                response,
                RouteArgumentConverter.Convert<T1>(arguments[0]),
                RouteArgumentConverter.Convert<T2>(arguments[1]),
                RouteArgumentConverter.Convert<T3>(arguments[2]),
                RouteArgumentConverter.Convert<T4>(arguments[3]),
                RouteArgumentConverter.Convert<T4>(arguments[4]),
                RouteArgumentConverter.Convert<T4>(arguments[5]),
                RouteArgumentConverter.Convert<T4>(arguments[6])
            );
        }
    }

    public class Route<T1, T2, T3, T4, T5, T6, T7, T8> : Route
    {
        private Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, T4, T5, T6, T7, T8, HttpListenerResponse> Target;

        public Route(string method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, T4, T5, T6, T7, T8, HttpListenerResponse> target, bool closeResponse = true)
        {
            this.Method = method;
            this.Syntax = syntax;
            this.Target = target;
            this.CloseResponse = closeResponse;
        }

        public Route(HttpRequestMethod method, string syntax, Func<HttpListenerRequest, HttpListenerResponse, T1, T2, T3, T4, T5, T6, T7, T8, HttpListenerResponse> target, bool closeResponse = true)
            : this(method.ToString(), syntax, target, closeResponse) { }

        public override void Invoke(HttpListenerRequest request, HttpListenerResponse response, params string[] arguments)
        {
            this.Target.DynamicInvoke(
                request,
                response,
                RouteArgumentConverter.Convert<T1>(arguments[0]),
                RouteArgumentConverter.Convert<T2>(arguments[1]),
                RouteArgumentConverter.Convert<T3>(arguments[2]),
                RouteArgumentConverter.Convert<T4>(arguments[3]),
                RouteArgumentConverter.Convert<T4>(arguments[4]),
                RouteArgumentConverter.Convert<T4>(arguments[5]),
                RouteArgumentConverter.Convert<T4>(arguments[6]),
                RouteArgumentConverter.Convert<T4>(arguments[7])
            );
        }
    }
}
