### codetube
    Copyright (C) 2011 payload payload@lavabit.com
    Copyright (C) 2011 dodo dodo.the.last@gmail.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>
###

connect = require('connect')


inverted_regex = (str, opts) -> # not really, but would be nice if :P
    str = new String(str)
    return str unless opts
    rest = new String(opts)
    str = str.replace(/\*\?/g, opts ? "")
    str = str.replace(/\*/g  , opts)
    for own name, attr of opts
        str = str.replace(new RegExp(":#{name}\\?", 'g'), attr ? "")
        str = str.replace(new RegExp(":#{name}",    'g'), attr)
    if str.length > 2 and str.charAt(str.length - 1) is "/"
        str = str[0 ... str.length-1]
    str


method_proxy = () ->
    app = order:[]
    for method in connect.router.methods.concat(['all', 'del'])
        app[method] = do (method) -> (controller, path) ->
            app.order.push({method, controller, path})
            controller.url ?= (opts) ->
                inverted_regex(path, opts)
            controller.url[method] ?= (opts) ->
                inverted_regex(path, opts)
    app


class Router
    constructor: (@create_routes) ->
        @controller = {}

    load: () =>
        @methods = method_proxy()
        @create_routes(@methods)
        @loaded = yes

    bind: (server) =>
        throw new Error("routes not loaded!") unless @loaded
        for url in @methods.order
            do (url) ->
                server[url.method](url.path, url.controller)
        yes # this is for avoiding an array

# exports

module.exports = Router

