/*!
 * onDomReady.js 1.4.0 (c) 2013 Tubal Martin - MIT license
 *
 * Specially modified to work with Holder.js
 */

function _onDomReady(win) {
    //Lazy loading fix for Firefox < 3.6
    //http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html
    if (document.readyState == null && document.addEventListener) {
        document.addEventListener("DOMContentLoaded", function DOMContentLoaded() {
            document.removeEventListener("DOMContentLoaded", DOMContentLoaded, false);
            document.readyState = "complete";
        }, false);
        document.readyState = "loading";
    }
    
    var doc = win.document,
        docElem = doc.documentElement,
    
        LOAD = "load",
        FALSE = false,
        ONLOAD = "on"+LOAD,
        COMPLETE = "complete",
        READYSTATE = "readyState",
        ATTACHEVENT = "attachEvent",
        DETACHEVENT = "detachEvent",
        ADDEVENTLISTENER = "addEventListener",
        DOMCONTENTLOADED = "DOMContentLoaded",
        ONREADYSTATECHANGE = "onreadystatechange",
        REMOVEEVENTLISTENER = "removeEventListener",
    
        // W3C Event model
        w3c = ADDEVENTLISTENER in doc,
        _top = FALSE,
    
        // isReady: Is the DOM ready to be used? Set to true once it occurs.
        isReady = FALSE,
    
        // Callbacks pending execution until DOM is ready
        callbacks = [];
    
    // Handle when the DOM is ready
    function ready( fn ) {
        if ( !isReady ) {
    
            // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
            if ( !doc.body ) {
                return defer( ready );
            }
    
            // Remember that the DOM is ready
            isReady = true;
    
            // Execute all callbacks
            while ( fn = callbacks.shift() ) {
                defer( fn );
            }
        }
    }
    
    // The ready event handler
    function completed( event ) {
        // readyState === "complete" is good enough for us to call the dom ready in oldIE
        if ( w3c || event.type === LOAD || doc[READYSTATE] === COMPLETE ) {
            detach();
            ready();
        }
    }
    
    // Clean-up method for dom ready events
    function detach() {
        if ( w3c ) {
            doc[REMOVEEVENTLISTENER]( DOMCONTENTLOADED, completed, FALSE );
            win[REMOVEEVENTLISTENER]( LOAD, completed, FALSE );
        } else {
            doc[DETACHEVENT]( ONREADYSTATECHANGE, completed );
            win[DETACHEVENT]( ONLOAD, completed );
        }
    }
    
    // Defers a function, scheduling it to run after the current call stack has cleared.
    function defer( fn, wait ) {
        // Allow 0 to be passed
        setTimeout( fn, +wait >= 0 ? wait : 1 );
    }
    
    // Attach the listeners:
    
    // Catch cases where onDomReady is called after the browser event has already occurred.
    // we once tried to use readyState "interactive" here, but it caused issues like the one
    // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
    if ( doc[READYSTATE] === COMPLETE ) {
        // Handle it asynchronously to allow scripts the opportunity to delay ready
        defer( ready );
    
    // Standards-based browsers support DOMContentLoaded
    } else if ( w3c ) {
        // Use the handy event callback
        doc[ADDEVENTLISTENER]( DOMCONTENTLOADED, completed, FALSE );
    
        // A fallback to window.onload, that will always work
        win[ADDEVENTLISTENER]( LOAD, completed, FALSE );
    
    // If IE event model is used
    } else {
        // Ensure firing before onload, maybe late but safe also for iframes
        doc[ATTACHEVENT]( ONREADYSTATECHANGE, completed );
    
        // A fallback to window.onload, that will always work
        win[ATTACHEVENT]( ONLOAD, completed );
    
        // If IE and not a frame
        // continually check to see if the document is ready
        try {
            _top = win.frameElement == null && docElem;
        } catch(e) {}
    
        if ( _top && _top.doScroll ) {
            (function doScrollCheck() {
                if ( !isReady ) {
                    try {
                        // Use the trick by Diego Perini
                        // http://javascript.nwbox.com/IEContentLoaded/
                        _top.doScroll("left");
                    } catch(e) {
                        return defer( doScrollCheck, 50 );
                    }
    
                    // detach all dom ready events
                    detach();
    
                    // and execute any waiting functions
                    ready();
                }
            })();
        }
    }
    
    function onDomReady( fn ) {
        // If DOM is ready, execute the function (async), otherwise wait
        isReady ? defer( fn ) : callbacks.push( fn );
    }
    
    // Add version
    onDomReady.version = "1.4.0";
    // Add method to check if DOM is ready
    onDomReady.isReady = function(){
        return isReady;
    };

    return onDomReady;
}

module.exports = typeof window !== "undefined" && _onDomReady(window);