/**
 * Core DISQUS module.
 */

var DISQUS = (function () {
    var doc = window.document,
        scripts = doc.getElementsByTagName("script");

    var container, // Container we use to attach SCRIPT elements
        jobs,      // Queue of functions to run (see defer method)
        dir,       // This file's directory URL (used to load other files)
        pub;       // Public methods

    container = (doc.getElementsByTagName('head')[0] || doc.getElementsByTagName('body')[0]);
    jobs = { running: false, timer: null, queue: [] };
    pub = {};

    dir = scripts[scripts.length - 1].src.split("/");
    dir.pop();
    dir = dir.join("/");
    
    // Defer func's execution until condition is true
    pub.defer = function (condition, func) {
        function beat() {
            if (jobs.queue.length === 0) {
                jobs.running = false;
                clearInterval(jobs.timer);
                return;
            }

            var pair = jobs.queue.shift();
            if (pair[0]()) {
                pair[1]();
            } else {
                jobs.queue.push(pair);
            }
        }

        jobs.queue.push([condition, func]);
        beat();
        if (!jobs.running) {
            jobs.running = true;
            jobs.timer = setInterval(beat, 100);
        }

        // Return number of jobs remaining
        return jobs.queue.length;
    };

    pub.each = function (collection, callback) {
        var length = collection.length,
            forEach = Array.prototype.forEach;

        if (!isNaN(length)) {
            // Treat collection as an array
            if (forEach) {
                forEach.call(collection, callback);
            } else {
                for (var i = 0; i < length; i++) {
                    callback(collection[i], i, collection);
                }
            }
        } else {
            // Treat collection as an object
            for (var key in collection) {
                if (collection.hasOwnProperty(key)) {
                    callback(collection[key], key, collection);
                }
            }
        }
    };

    // Merge the contents of two or more objects together into the first object
    // (or DISQUS, if called with one argument).
    pub.extend = function () {
        var target, args;

        if (arguments.length <= 1) {
            target = pub;
            args = [arguments[0] || {}];
        } else {
            target = arguments[0] || {};
            args = Array.prototype.slice.call(arguments, 1);
        }

        for (var i = 0; i < args.length; i++) {
            for (var prop in args[i]) {
                if (args[i].hasOwnProperty(prop)) {
                    target[prop] = args[i][prop];
                }
            }
        }

        return target;
    };

    // Load files using relative or absolute paths
    pub.load = function (path, skipCache) {
        path = (path.slice(0, 4) != "http" ? dir + "/" : "") + path;
        if (skipCache) {
            var last = path.slice(path.length - 1);
            path += (last != "&" && last != "?" ? "?" : "") +
                    (new Date()).getTime();
        }

        var script = doc.createElement("script");
        script.src = path;
        script.async = true;
        script.charset = "UTF-8";
        container.appendChild(script);

        return script;
    };

    return pub;
}());

// Stubs for packages
DISQUS.extend({
    comments: {},
    host:     {},
    net:      {},
    widgets:  {}
});
