// This block code shouldn't depend on no deps
// Require porthole
// Export as module
(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define(factory);
    } else if (typeof exports === 'object') {
        module.exports = factory(root);
    } else {
        root.Viewer = factory(root);
    }
})(window || this, function () {

    var document = window.document;

    // Write some util methods
    function createStyleSheet(href, id) {

        if (typeof href !== 'undefined') {
            var element = document.createElement('link');
            element.type = 'text/css';
            element.rel = 'stylesheet';
            element.href = href;
        }
        else {
            var element = document.createElement('style');
            element.type = 'text/css';
            element.id = id;
        }

        document.getElementsByTagName('head')[0].appendChild(element);
        var sheet = document.styleSheets[document.styleSheets.length - 1];

        if (typeof sheet.addRule === 'undefined')
            sheet.addRule = function (selectorText, cssText, index) {

                if (typeof index === 'undefined')
                    index = sheet.cssRules.length;

                sheet.insertRule(selectorText + ' {' + cssText + '}', index);
            };

        if (typeof sheet.removeRule === 'undefined')
            sheet.removeRule = sheet.deleteRule;

        return sheet;
    }

    function convertToText(obj) {
        //create an array that will later be joined into a string.
        var string = [];

        //is object
        //    Both arrays and objects seem to return "object"
        //    when typeof(obj) is applied to them. So instead
        //    I am checking to see if they have the property
        //    join, which normal objects don't have but
        //    arrays do.
        if (typeof (obj) === "object" && (obj.join === undefined)) {
            // string.push("{");
            for (prop in obj) {

                string.push(prop, ": ", convertToText(obj[prop]), ";");
            }
            // string.push("}");

            //is array
        } else if (typeof (obj) === "object" && !(obj.join === undefined)) {
            string.push("[");
            for (prop in obj) {
                string.push(convertToText(obj[prop]), ",");
            }
            string.push("]");

            //is function
        } else if (typeof (obj) === "function") {
            string.push(obj.toString());

            //all other values can be done with JSON.stringify
        } else {
            string.push(JSON.stringify(obj));
        }

        return string.join("");
    }

    // Construction
    function Viewer(opts) {
        // Using those opts to pass to our viewer
        this.opts = opts;
        this.styleId = "viewerStyle";
        this.defaultViewerClass = "viewer-dialog";
        this.defaultIframeClass = "viewer-dialog-frame";
        this.defaultIframeName = "viewerIframe";
        //this.frameSource = "http://localhost:8383/HTML_Viewer/index.html"; // "http://localhost:8383/Viewer/?iframe=true"; //
        this.windowProxy = null;
        this.onMessage = null;
    }

    // Init the viewer
    Viewer.prototype.init = function () {
        // Create CSS write on body
        var sheet = createStyleSheet(undefined, this.styleId);

        setTimeout(function () {
            sheet.addRule(".viewer-dialog-content", "font-size: 0;padding: 0; width: 100%; height: 100%");
        }, 150);

        // Create elements
        var dialog = document.createElement("div"),
            dialogContent = document.createElement("div"),
            iframe = document.createElement("iframe"),
            container = this.opts.containerId ? document.getElementById(this.opts.containerId) : document.getElementsByTagName("body")[0];

        if (this.opts.viewerClass) {

            // Viewer classes
            dialog.className = this.opts.viewerClass + " " + this.defaultViewerClass;
        }
        else {

            // Implement css
            dialog.className = this.defaultViewerClass;
            // Default CSS
            sheet.addRule("." + this.defaultViewerClass, "position: absolute; top: 0; left: 0; background-color: #fff; border: 1px solid #acacac; z-index: 1001;");
            // var css = computeCss();
            dialog.style.top = dialog.style.bottom = "10px"; // css.top + "px";
            dialog.style.left = dialog.style.right = "15px"; // css.left + "px";
        }

        if (this.opts.iframeClass) {
            // Create an iframe
            iframe.className = this.opts.iframeClass + " " + this.defaultIframeClass;
        }
        else {
            // Create an iframe
            iframe.className = this.defaultIframeClass;
            // Iframe CSS
            sheet.addRule("." + this.defaultIframeClass, "width: 100%; height: 100%; border: 0; overflow: hidden");
        }

        // Then create a wrapper for iframe
        dialogContent.className = "viewer-dialog-content";

        // Put the source
        iframe.src = this.opts.frameSource;
        iframe.setAttribute("name", this.defaultIframeName);

        // Append children
        dialogContent.appendChild(iframe);
        dialog.appendChild(dialogContent);

        container.appendChild(dialog);

        // dialogContent.style.width = css.width + "px";
        // dialogContent.style.height = css.height + "px";

        // Cache the context
        var _this = this;

        this.onMessage = function (mEvent) {

            /*
             messageEvent.origin: Protocol and domain origin of the message
             messageEvent.data: Message itself
             messageEvent.source: Window proxy object, useful to post a response
             */

            if (mEvent.origin === _this.opts.viewerOrigin) {

                if (mEvent.data === 'viewerFullLoaded') {

                    // Display secrect button
                    _this.opts.showCloseButton = true;


                    // Point the exact frame source
                    _this.windowProxy.post(_this.opts, _this.opts.viewerOrigin);
                } else if (mEvent.data === 'closeViewer') {

                    // Remove the iframe
                    iframe.parentNode.removeChild(iframe);

                    // Remove the parent
                    dialog.parentNode.removeChild(dialog);

                    // Remove event this first
                    // window.removeEventListener( "message", removeIframe, false );

                    // Remove css first
                    var style = document.getElementById(_this.styleId);
                    style && style.parentNode.removeChild(style);

                    _this.opts.onClose && _this.opts.onClose();
                }
            }
        };

        // Create a proxy window to send to and receive
        // messages from the iFrame
        this.windowProxy = new Porthole.WindowProxy(_this.opts.frameSource, this.defaultIframeName);
        // Register an event handler to receive messages;
        this.windowProxy.addEventListener(this.onMessage);
    };

    Viewer.prototype.destroy = function () {
        // remove event listener
        this.windowProxy.removeEventListener(this.onMessage);
    };

    // Should check confict name first
    // Set as global object
    // window.Viewer = Viewer;
    return Viewer;
});
