/* appjet:version 0.1 */
/* appjet:library */
// Copyright (c) 2009, Herbert Vojčík
// Licensed by MIT license (http://www.opensource.org/licenses/mit-license.php)
/** Decoded segments of full path */
request.fullPathSegments = request.path.split('/').map(decodeURIComponent);
/** Decoded full path */
request.fullPath = request.fullPathSegments.join('/');
/**@ignore*/
request.fullPathSegments.of = request.fullPath;
/**
  * 
Enhanced dispatcher function. Dispatches according to request.fullPath. Allows for:
  * - nonalphanumeric characters in path. Serve /robots.txt with 
get_robots$txt 
  * - subpath matching: 
  *   - Serve /foo/, /foo/bar and /foo/bar/baz from 
get_foo_ 
  *   get_foo_main serves only the /foo/ path, but not the /foo/bar, nor /foo 
  *   - If there are more functions matching, the most specific (the longest one) wins
 
  *   request.pagePath is set to path of your handler (/foo), request.pathTail is set to the rest(/bar). 
  *   request.fullPath contains the full path in decoded form 
  *   - request.fullPathSegments, request.pagePathSegments and request.pathTailSegments contain segments of these paths
 
  * 
 
  * 404 handling is different: assign your 404 handler to dispatchPlus.f404
  * If you pass arguments to dispatchPlus call, they are passed to handler function. No more need for globals to pass initial information to handler functions.
  * 
  */
function dispatchPlus(arg1, arg2, etc) {
    _rejuvenateFullPathSegments();
    var selectorSegments = request.fullPathSegments.map(function(x) {
        return [x.replace(/[\W]/g,'$$'), "_"];
    });
    selectorSegments.push([selectorSegments.pop()[0] || "main"]);
    var handler, handlerSegments, selector = arguments.callee[request.method] || request.method.toLowerCase();
    selectorSegments.forEach(function(segment, index) {
        selector += segment.join('');
        var candidate = appjet._internal.global[selector];
        if (typeof candidate === "function") {
        	handler = candidate;
        	handlerSegments = index + 1;
        }
    });
    if (handler) {
        request.pagePathSegments = request.fullPathSegments.slice(0, handlerSegments);
        request.pathTailSegments = request.fullPathSegments.slice(handlerSegments);
        request.pagePath = request.pagePathSegments.join('/');
        request.pathTail = request.fullPath.substring(request.pagePath.length);
    }
    (handler || arguments.callee.f404).apply(null, arguments);
}
/** The 404 (page not found) handler. You can replace it with your own. */
dispatchPlus.f404 = function() {
    response.setStatusCode(404);
    printp("Path not found: ", request.fullPath);
    print(request);
    response.stop();
};
/** The prefix for GET method dispatcher functions. Default is "get", you can change it. */
dispatchPlus.GET = "get";
/** The prefix for HEAD method dispatcher functions. Default is "get", you can change it. */
dispatchPlus.HEAD = "get";
/** The prefix for POST method dispatcher functions. Default is "post", you can change it. */
dispatchPlus.POST = "post";
/** The prefix for CRON method dispatcher functions. Default is "cron", you can change it. */
dispatchPlus.CRON = "cron";
function _rejuvenateFullPathSegments() {
    if (request.fullPathSegments.of === request.fullPath) return;
    request.fullPathSegments = request.fullPath.split('/');
    request.fullPathSegments.of = request.fullPath;
}
/* appjet:server */
import("lib-app/dispatch-plus");
/**@ignore*/
function printRequest() {
    printp({
        pagePath: request.pagePath,
        pagePathSegments: request.pagePathSegments,
        fullPath: request.fullPath,
        fullPathSegments: request.fullPathSegments,
        pathTail: request.pathTail,
        pathTailSegments: request.pathTailSegments
    });
};
/**@ignore*/
function get_(arg) {
    printp("Serviced by ", CODE(arguments.callee));
    printp("Try these links:");
    print(UL(
        LI(A({href:"/long/path/here.2"}, "/long/path/here.2")),
        LI(A({href:"/papľuh/path-ing/"}, "/papľuh/path-ing/"))
    ));
    printp("Hello, ", arg, "!");
    printRequest();
}
/**@ignore*/
function get_papľuh_(arg) {
    printp("Serviced by ", CODE(arguments.callee));
    printp("Hello, ", arg, "!");
    printRequest();
}
/**@ignore*/
var get_papľuh_path$ing = "This is not a function";
/**@ignore*/
function get_long_path_() {
    throw new Error("This should not be called.");
}
/**@ignore*/
function get_long_path_here$2(arg) {
    printp("Serviced by ", CODE(arguments.callee));
    printp("Hello, ", arg, "!");
    printRequest();
}
/**@ignore*/
function get_long_path_here$2_() {
    throw new Error("This should not be called.");
}
/**@ignore*/
function get_long_path_here$2_main() {
    throw new Error("This should not be called.");
}
printp("Features of extended dispatcher:");
print(UL(
    LI("Any nonalphanumeric characters (except the slash, of course) are replaced by '$' (dollar sign). Now you can serve /robots.txt by get_robots$txt function."),
    LI("You can put a handler only to a beginning part of the path, if you use name like get_beginning_. This serves all paths in the form /beginning/... The path is broken to request.pagePath (the first part) and request.pathTail (the rest)."),
    LI("If you end function with _main, it will not serve subpaths (it only matches to full path ending with / (a slash)."),
    LI("If there are more subpath handlers and full path handlers, the most specific (the one that matches the longest part of the path) is chosen. If case of get_path_ and get_path_main, the latter will be chosen to service /path/, but the former to service /path/some/more."),
    LI("404 is handled other way: you specify your 404 handler by assigning it to dispatchPlus.f404 before placing a call."),
    LI("Any arguments you put in dispatchPlus call, gets copied into your handler function.")
));
printp("The statments issued in this minitest is ", CODE('dispatchPlus("world")'));
dispatchPlus("world");