/**
 * @param {function} callback
 * @param {string} target
 * @param {Array} resources
 * @constructor
 */
$.frameReady = function (callback, targetSelector, resources) {
    /**
     * @type {window}
     */
    var targetWindow = document.querySelector(targetSelector);
    /**
     * @type {Document}
     */
    var targetDocument = null;

    var scripts = resources.filter(function (resource) {
        return resource.type === 'script';
    });
    var stylesheets = resources.filter(function (resource) {
        return resource.type === 'stylesheet';
    });

    var scriptsCount = (function () {
        var count = 0;

        /**
         * @param {Object} parentScript
         */
        function countScripts(parentScript) {
            count++;

            if (!parentScript.hasOwnProperty('deps')) {
                return;
            }

            parentScript.deps.forEach(countScripts);
        }

        scripts.forEach(countScripts);

        return count;
    })();
    var scripsLoadedCount = 0;

    targetWindow.onload = function () {
        scripsLoadedCount = 0;

        targetDocument = targetWindow.contentDocument;

        scripts.forEach(function (script) {
            createScript(script);
        });

        stylesheets.forEach(function (stylesheet) {
            createStylesheet(stylesheet);
        });
    };

    /**
     * @param {Object} script
     */
    function createScript(script) {
        /**
         * @type {HTMLScriptElement}
         */
        var elParent = targetWindow.contentDocument.createElement('script');
        elParent.async = false;
        elParent.onload = function () {
            scripsLoadedCount++;

            if (!script.hasOwnProperty('deps')) {
                tryExecuteCallback();

                return;
            }

            script.deps.forEach(function (scriptB) {
                createScript(scriptB);
            });
        };
        elParent.setAttribute('src', script.src);

        targetDocument.body.appendChild(elParent);
    }

    /**
     * @param {Object} stylesheet
     */
    function createStylesheet(stylesheet) {
        /**
         * @type {HTMLLinkElement}
         */
        var el = targetWindow.contentDocument.createElement('link');
        el.setAttribute('href', stylesheet.src);
        el.setAttribute('rel', "stylesheet");
        el.setAttribute('type', "text/css");
        if (targetDocument.head) {
            targetDocument.head.appendChild(el);
        }
    }

    function tryExecuteCallback() {
        if (scripsLoadedCount < scriptsCount) {
            return;
        }

        targetWindow.contentWindow.eval('(' + callback.toString() + ')();');
    }
};
