Ext.namespace("POD");

// Too much regex for my liking.  A JQuery plugin would be cleaner, but this works.
// http://stackoverflow.com/questions/901115/get-querystring-with-jquery/901144#901144
POD.qsVal = function ( name ) {
    name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
    var regexS = "[\\?&]"+name+"=([^&#]*)";
    var regex = new RegExp( regexS );
    var results = regex.exec( window.location.href );
    if( results == null )
        return "";
    else
        return results[1];
}

POD.addTab = function (title, url, section,module) {
    if(Ext.getCmp("tab-"+title)) {
        Ext.getCmp("tab-"+title).show();
        return Ext.getCmp("tab-"+title);
    }
    POD.clearTOC();
    var tab = POD.tabs.add({
        title: title, 
        id: "tab-" + title,
        closable: true,
        closeAction: "hide",
        autoLoad: {url : url,
        loadScripts: true,
        callback : function() {POD.scrollToSection(tab, section,module);}},
        autoScroll: true
    });
    tab.show();
    return tab;
}

POD.proxyLink = function(link) {
    var re = new RegExp("^" + Ext.escapeRe("[% root %]"));
    if(!re.test(link.href)) return true;
    var module = link.href.replace(new RegExp(Ext.escapeRe("[% root %]/module/")), "");

    var parts = module.split(/#/);
    section = unescape(parts[1]);
    module = parts[0];
    if(re.test(module)) {
        module = POD.tabs.getActiveTab().getId().replace(/tab-/, "");
    }
    var tab = POD.addTab(module, link.href, section, module);
    POD.scrollToSection(tab, section, module);
    return false;
}

POD.scrollToSection = function(tab, section, module){
    var el = document.getElementById("section-"+module+"-"+section);
    if(el){
        var top = (Ext.fly(el).getOffsetsTo(tab.body)[1]) + tab.body.dom.scrollTop;
        tab.body.scrollTo('top', top, {duration:.5});
    }
}

POD.reloadTree = function(e) {
    if(!e.target.value) {
        POD.tree.getLoader().dataUrl = '[% root %]/modules';
        POD.tree.getLoader().load(POD.tree.root);
        return;
    }
    POD.tree.getLoader().dataUrl = '[% root %]/modules/'+e.target.value;
    POD.tree.getLoader().load(POD.tree.root);
}

POD.tree = new Ext.tree.TreePanel({
    title:           "Modules",
    autoScroll:      true,
    animate:         true,
    rootVisible:     false,
    split:           true,
    region:          "center",
    containerScroll: true,
    listeners:  {
        click: function(node) { POD.addTab(node.attributes.name, "[% root %]/module/"+node.attributes.name) }},
        loader: new Ext.tree.TreeLoader({
            dataUrl:   '[% root %]/modules',
            autoLoad:  false,
            listeners: { 
                beforeload: function() { POD.tree.getEl().mask('Modules are being loaded') }, 
                load: function() { 
                    POD.tree.getEl().unmask();
                    if([% expand_module_tree_on_load %]) {
                        var old = POD.tree.animate;
                        POD.tree.animate = false;
                        POD.tree.expandAll();
                        POD.tree.animate = old;
                    }
                }
            }
        }),
    tbar: [
            new Ext.form.TextField({
                width: 130,
                emptyText: 'Find a Class',
                listeners: {
                    render: function(f){
                        f.el.on('keydown', POD.reloadTree, f, {buffer: 350});
                    }
                }
            }), 
            ' ',
            ' ',
            {
                handler: function (){POD.tree.expandAll()},
                tooltip: 'Expand all nodes',
                iconCls:"icon-expand-all"
            },
            {
                handler: function (){POD.tree.collapseAll()},
                tooltip: 'Collapse all nodes',
                iconCls:"icon-collapse-all"}
        ]
});

var root = new Ext.tree.AsyncTreeNode({
    text: 'mods',
    expanded:true,
});

POD.tree.setRootNode(root);
POD.filter = new Ext.tree.TreeFilter(POD.tree, {
    clearBlank: true,
    autoClear: true
});

POD.TOC = new Ext.tree.TreePanel({
    title:       "TOC",
    autoScroll:  true,
    height:      200,
    collapsible: true,
    animate:     true,
    rootVisible: false,
    loader:      new Ext.tree.TreeLoader(),
    split:       true,
    region:      "north",
    listeners: {
        click: function(node) { 
            var module = POD.tabs.getActiveTab().getId().replace(/tab-/,"");
            POD.scrollToSection(POD.tabs.getActiveTab(), node.text, module);
        }
    }
});

POD.TOC.setRootNode(new Ext.tree.AsyncTreeNode({
    text: 'mods',
    expanded:false
}));

POD.populateTOC = function (nodes, root) {
    for(var i = 0; i < nodes.length; i++) {
        var n = POD.TOC.getLoader().createNode(nodes[i]);
        if (n) {
            root.appendChild(n);
        }
    }
}

POD.leftColumn = new Ext.Panel({
    layout: "border",
    region: "west",
    split:  true,
    width:  200,
    items:  [POD.tree, POD.TOC]
});

POD.TOCs = {};

POD.clearTOC = function() {
    while (POD.TOC.root.firstChild) {
        POD.TOC.root.removeChild(POD.TOC.root.firstChild);
    }
}

POD.setTOC = function (nodes) {
    POD.clearTOC();
    POD.TOCs[POD.tabs.getActiveTab().getId()] = nodes;
    POD.populateTOC(nodes, POD.TOC.root);
}


POD.searchStore = new Ext.data.Store( {
    proxy: new Ext.data.HttpProxy( {
        method :'POST',
        url :'[% root %]/search'
    }),
    reader: new Ext.data.JsonReader( {
            root :'module',
            totalProperty :'matches'
            }, [ {
                name :'link',
                mapping :'link'
            }, {
                name :'name',
                mapping :'name'
            }, {
                name :'released',
                mapping :'released'
            }, {
                name :'version',
                mapping :'version'
            }, {
                name :'description',
                mapping :'description'
            }, {
                name :'author',
                mapping :'author'
            }]
    )
});

var resultTpl = new Ext.XTemplate(
    '<tpl for="."><div class="search-item">',
    '<span>{released}',
    '</span><h3>{name}</h3> (Version {version})<br>{description}</div></tpl>');


var Memoria = {};
Memoria.Search = {};
Memoria.Search.InstantAdd = new (function() {

    this.init = function(combo) {
        this.combo = combo;
        var add = new Ext.Layer({cls: "x-combo-list", html: "test1234", zindex: "100"});  
        var lw = combo.listWidth || Math.max(combo.wrap.getWidth(), combo.minListWidth);
        add.setWidth(lw);
        add.alignTo(combo.wrap, combo.listAlign);
        this.content = add.createChild({cls:'search-item'});
        this.add = add;
        new Ext.KeyNav(combo.el, {
            esc: function() { Memoria.Search.InstantAdd.hide() },
            enter: function() {
                Memoria.Search.InstantAdd.hide();
                Memoria.Clients.add(stringToName(Memoria.Search.InstantAdd.combo.getValue()));
            }
        })
        combo.el.on("keydown", this.hide , this);
        this.tpl = new Ext.XTemplate('<h3 style="text-align: center">Sorry. Couldn\'t find anything.</h3>');
    }

    this.show = function () {
        if(!this.combo.getValue()) return;
        this.add.show();
        this.content.dom.innerHTML = this.tpl.apply({name: this.combo.getValue()});
    }

    this.hide = function () {
        this.add.dom.style.visibility=""; // Do not use this.add.hide() BUG?
    }
})();

POD.tabs = new Ext.TabPanel({
    region:         'center',
    activeTab:       0,
    autoScroll:      true,
    margins:         "5 5 5 5",
    enableTabScroll: true,
    listeners: {
        tabchange: function(panel, tab) {
            if(POD.TOCs[tab.getId()])
              POD.setTOC(POD.TOCs[tab.getId()]);
            if(tab.getId() == "search-box")
              POD.clearTOC();
        }
    },
    tools: [
        {
            id: "print", 
            handler: function() {
                window.open("[% root %]/module/"+tabs.getActiveTab().id.replace(/tab-/,"")); }
        }, {
            id: "close",
            handler: function () {
                tabs.items.each(function(el){if(new RegExp("tab-").test(el.id)) tabs.remove(el)})
            }
        }
    ],
});

//
// For some reason the following order matters.
// 

// Display documentation for the permalink
var permalink = POD.qsVal("permalink");
if(permalink) {
    POD.addTab(permalink, "[% root %]/module/" + permalink);
}

// Show the home tab only if we're configured to 
if([% show_home_tab %]) {
    POD.tabs.add({
        layout: 'form',
        title:  "Home",
        id:     "search-box",
        frame:  false,
        border: false,
        autoLoad: {
            url: "[% root %]/home_tab_content",
            callback: function() { POD.configSearchCombo(); },
            loadScripts: true,
        },
    });
}

if("[% initial_module %]") {
    // Display a perldoc tab on startup
    POD.addTab("[% initial_module %]", "[% root %]/module/[% initial_module %]");
}

POD.configSearchCombo = function () {
    var search = new Ext.form.ComboBox( {
        store:      POD.searchStore,
        typeAhead:  false,
        minChars:   3,
        queryParam: 'value',
        emptyText:  "Search the CPAN for modules",
        loadingText:'Searching ...',
        width:       470,
        pageSize:    50,
        hideTrigger: true,
        tpl:         resultTpl,
        applyTo:     Ext.getDom('search'),
        itemSelector:'div.search-item',
        listeners: {
            render: function(combo) {
                Memoria.Search.InstantAdd.init(combo)
            },
            collapse: function() {
                Memoria.Search.InstantAdd.show()
            },
            select: function(combo, record) { 
                POD.addTab(record.get("name"), "[% root %]/module/"+record.get("name"));
                Memoria.Search.InstantAdd.hide();
            },
            blur: function() {
                Memoria.Search.InstantAdd.hide();
            }
        }
    });
    Ext.getDom('search').focus(100, true);
}

Ext.onReady(function(){
    Ext.Updater.defaults.loadScripts = true;
  
    var viewport = new Ext.Viewport({
        layout:'border',
        items:[POD.tabs, POD.leftColumn]
    });
});