import re
from collections import namedtuple
from .exceptions import NotFound, InvalidUsage

Route = namedtuple("Route", ['handler', 'methods', 'pattern', 'parameters'])
Parameter = namedtuple("Parameter", ['name', 'cast'])

REGEX_TYPES = {
    "string": (None, "[^/]+"),
    "int": (int, "\d+"),
    "number": (float, "[0-9\\.]+"),
    "alpha": (None, "[A-Za-z]+"),
}


class Router:
    """
    Router supports basic routing with parameters and method checks
    Usage:
        @sanic.route('/my/url/<my_parameter>', methods=['GET', 'POST', ...])
        def my_route(request, my_parameter):
            do stuff...

    Parameters will be passed as keyword arguments to the request handling
    function provided Parameters can also have a type by appending :type to
    the <parameter>.  If no type is provided, a string is expected.  A regular
    expression can also be passed in as the type

    TODO:
        This probably needs optimization for larger sets of routes,
        since it checks every route until it finds a match which is bad and
        I should feel bad
    """
    routes = None

    def __init__(self):
        self.routes = []

    def add(self, uri, methods, handler):
        """
        Adds a handler to the route list
        :param uri: Path to match
        :param methods: Array of accepted method names.
        If none are provided, any method is allowed
        :param handler: Request handler function.
        When executed, it should provide a response object.
        :return: Nothing
        """

        # Dict for faster lookups of if method allowed
        methods_dict = None
        if methods:
            methods_dict = {method: True for method in methods}

        parameters = []

        def add_parameter(match):
            # We could receive NAME or NAME:PATTERN
            parts = match.group(1).split(':')
            if len(parts) == 2:
                parameter_name, parameter_pattern = parts
            else:
                parameter_name = parts[0]
                parameter_pattern = 'string'

            # Pull from pre-configured types
            parameter_regex = REGEX_TYPES.get(parameter_pattern)
            if parameter_regex:
                parameter_type, parameter_pattern = parameter_regex
            else:
                parameter_type = None

            parameter = Parameter(name=parameter_name, cast=parameter_type)
            parameters.append(parameter)

            return "({})".format(parameter_pattern)

        pattern_string = re.sub("<(.+?)>", add_parameter, uri)
        pattern = re.compile("^{}$".format(pattern_string))

        route = Route(
            handler=handler, methods=methods_dict, pattern=pattern,
            parameters=parameters)
        self.routes.append(route)

    def get(self, request):
        """
        Gets a request handler based on the URL of the request, or raises an
        error
        :param request: Request object
        :return: handler, arguments, keyword arguments
        """

        route = None
        args = []
        kwargs = {}
        for _route in self.routes:
            match = _route.pattern.match(request.url)
            if match:
                for index, parameter in enumerate(_route.parameters, start=1):
                    value = match.group(index)
                    if parameter.cast:
                        kwargs[parameter.name] = parameter.cast(value)
                    else:
                        kwargs[parameter.name] = value
                route = _route
                break

        if route:
            if route.methods and request.method not in route.methods:
                raise InvalidUsage(
                    "Method {} not allowed for URL {}".format(
                        request.method, request.url), status_code=405)
            return route.handler, args, kwargs
        else:
            raise NotFound("Requested URL {} not found".format(request.url))

@@ -1828,18 +1828,27 @@
      par
-ts
+ameter_name
  = match
@@ -1860,185 +1860,198 @@
 p(1)
-.split(':')%0A            if len(parts) == 2:%0A                parameter_name, parameter_pattern = parts%0A            else:%0A                parameter_name = parts%5B0%5D%0A               
+%0A            parameter_pattern = 'string'%0A            if ':' in parameter_name:%0A                parameter_name, parameter_pattern = parameter_name.split(':', 1)%0A%0A            default = (None,
  par
@@ -2064,28 +2064,17 @@
 _pattern
- = 'string'%0A
+)
 %0A       
@@ -2137,232 +2137,108 @@
 ter_
-regex = REGEX_TYPES.get(parameter_pattern)%0A            if parameter_regex:%0A                parameter_type, parameter_pattern = parameter_regex%0A            else:%0A                parameter_type = None%0A%0A            parameter = 
+type, parameter_pattern = REGEX_TYPES.get(parameter_pattern, default)%0A            parameters.append(
 Para
@@ -2288,50 +2288,9 @@
 ype)
-%0A            parameters.append(parameter)%0A
+)
 %0A   
@@ -2309,14 +2309,14 @@
 urn 
-%22
+'
 (%7B%7D)
-%22
+'
 .for

Refactor add parameter