﻿/// <reference path="xtn-1.0.js" />
/// <reference path="jquery-1.4.3.min.js" />

(function ($) {

    var prv = {
        timer: undefined,
        itemsCache: undefined
    };

    xtn.extend({
        hash: {
            // key: regex, value : callback(hash, matched)
            callbacks: new xtn.def.baseTypes.Dictionary(),
            currentHash: '#',
            isEmpty: function () {
                return this.currentHash == '' || this.currentHash == '#' || this.currentHash == undefined;
            },
            load: function (force) {
                if (!prv.itemsCache || force) {
                    prv.itemsCache = this.currentHash.replace('#', '').split('/');
                    jQuery.each(prv.itemsCache, function (indx, el) {
                        if (el == '') {
                            prv.itemsCache[indx] = undefined;
                        }
                    });
                }
            },
            go: function (params) {

                if (!params) {
                    params = new Array();
                    jQuery.each(prv.itemsCache, function (indx, v) { if (v) { params.push(v); } });
                }

                xtn.fn.log("[hash] >>>> go: params");
                xtn.fn.log(params);
                xtn.fn.log("[hash] <<<< go: params");
                var path = '#/';

                if (typeof params != "string") {
                    jQuery.each(params, function (indx, el) { path += el + '/'; });
                } else {
                    if (!(params.match("/$") == '/')) {
                        params += '/'; // add trailing '/'
                    }
                    path += params;
                }
                xtn.fn.log("[hash] go: path - " + path);
                location.hash = path;
            },
            goPartial: function (srch, rplc) {
                this.load();
                var path = '#/';
                jQuery.each(prv.itemsCache, function (indx, v) { if (v) { path += v + '/'; } });
                xtn.fn.log("[hash] goPartial: path - " + path);

                if (!path.match(srch)) {
                    xtn.fn.log("[hash] goPartial: no match => pushing");
                    //if (!rplc.replace) return;
                    var s = rplc.replace(/\//gi, '');
                    prv.itemsCache.push(s);
                    xtn.fn.hash.go();
                    return;
                }

                var nPath = path.replace(srch, rplc);
                xtn.fn.log("[hash] goPartial: nPath - " + nPath);
                if (path != nPath) {
                    xtn.fn.log("[hash] goPartial: go!");
                    location.hash = nPath;
                }
            },
            get: function (indx, fallback) {
                this.load();
                var el = prv.itemsCache[indx + 1];
                xtn.fn.log("[hash] get: index " + indx + " value " + el);
                xtn.fn.log("[hash] return: " + (el ? "value" : (fallback ? "fallback" : "fallback - undefined")));
                return el ? el : (fallback ? fallback : undefined);
            },
            handleHashTimer: function () {
                if (this.currentHash != location.hash) {
                    this.currentHash = location.hash;
                    this.load(true);

                    xtn.fn.log("[hash] handleHashTimer hasChanged");

                    if (this.callbacks.getLength() > 0) {
                        this.callbacks.forEach(function (i, r) {
                            // i => key, r => regex
                            var mt = xtn.fn.hash.currentHash.match(r);
                            var c = xtn.fn.hash.callbacks.get(r);
                            if (mt && c) {
                                xtn.fn.log("[hash] match " + r.toString());
                                c.call(xtn.fn.hash, mt);
                            }
                        });
                    }
                }
            },
            init: function () {
                if (!prv.timer) { // allow only one instance
                    xtn.fn.log("[hash] init!");
                    prv.timer = setInterval(function () { xtn.fn.hash.handleHashTimer(); }, 500); // every 0.5 s
                }
            },
            kill: function () {
                if (prv.timer) {
                    xtn.fn.log("[hash] kill!");
                    clearInterval(prv.timer);
                }
            }
        }
    }, xtn.fn);


    //auto start?

    $(document).ready(function () {
        xtn.fn.hash.init();
    });

})(jQuery);
