(function($) {

    //create FrameDialog namespace
    $.FrameDialog = $.FrameDialog || {};

    //array for return values, placeholder
    $.FrameDialog._results = $.FrameDialog._results || {};

    //$.FrameDialog._isActive = $.FrameDialog._isActive || true;
    //set localized variables
    var OK = (window.localization && window.localization.OK) || "OK";
    var Cancel = (window.localization && window.localization.CANCEL) || "Cancel";
    var buttons = {};
    var winSize;


    buttons[OK] = function() {
        $(this).dialog("close");
    }
    buttons[Cancel] = function() {
        var frame = $(this);
        $.FrameDialog.clearResult(frame.attr("id"));
        frame.dialog("close");
    }

    //default options
    $.FrameDialog._defaultOptions = {
        modal: true,
        closeOnEscape: false,
        position: 'center',
        buttons: buttons,

        // TDR: class used to style the loading pane container
        loadingClass: null
    }

    var retry = false;

    $.FrameDialog.create = function(options) {
        try {
            winSize = { w: $(window).width(), h: $(window).height() }
            //generate unique id
            var uid = Math.random().toString(16).replace(".", "") + (new Date()).valueOf().toString(16);

            //extend frame dialog options with passed in options.
            var opts = $.extend(
				$.FrameDialog._defaultOptions,
				options || {}
			)

            var url = (opts && opts.url) || null;
            if (url === null)
                throw new Error("MODAL ERROR: Option 'url' not specified!"); //diagnostic error

            //clean up redundant forward slashes in the url.
            url = url.replace(/(^|[^:])\/+/g, "$1/");

            //remove url argument from options to be passed to dialog.
            try {
                delete opts.url;
            } catch (err) { }

            // TDR: create the loading pane and remove the loadingClass from the options hash
            var $loadingPane = $('<div></div>').addClass(opts.loadingClass);
            try { delete opts.loadingClass; } catch (err) { }

            //create iframe object
            //	object type="text/html doesn't seem to work in IE :(
            //	using iframe, which seems to work cross browser, tested in IE7, and Firefox 3.0.7
            var iframe = $("<iframe frameborder='0' scrolling='auto' background='transparent' />")
				.attr("id", uid + "-VIEW")
				.attr("name", uid + "-VIEW")
				.attr("src", url)
				.css("margin", "0")
				.css("border", "0")
				.css("padding", "0")
				.css("top", "0")
				.css("left", "0")
				.css("right", "0")
				.css("bottom", "0")
				.css("width", "100px")
				.css("height", "100px")

            // TDR: hide the iframe until it's assoicated page is loaded
                .css("visibility", "hidden")

            // TDR: on iframe page load, set the iframe's visiblity to visible and hide the loading pane
                .load(function(e) {
                    $(this).css('visibility', 'visible');
                    $loadingPane.hide();
                })
				;

            var overlay = $("<div>&nbsp;</div>")
                .attr("id", uid + "-OVERLAY")
				.css("position", "absolute")
				.css("margin", "0")
				.css("border", "0")
				.css("padding", "0")
				.css("top", "0")
				.css("left", "0")
				.css("right", "0")
				.css("bottom", "0")
				.css("width", "100%")
				.css("height", "100%")
				.css("display", "none")
				;

            var ret = $("<div />")
				.attr("id", uid)
				.css("margin", "0")
				.css("border", "0")
				.css("padding", "0")
				.css("top", "0")
				.css("left", "0")
				.css("right", "0")
				.css("bottom", "0")
				.css("overflow", "hidden")
				.hide()

            // TDR: append the loading pane to the dialog's container.
                .append($loadingPane)
				.append(iframe)
				.append(overlay)
				.appendTo(document.body)

            // TDR: on dialog open, set the height of the loading pane to that of the dialog's content container 
                .bind('dialogopen', function(event, ui) {
                    $loadingPane.height($loadingPane.closest('.ui-dialog-content').height());
                })
				.bind("dialogbeforeclose", function(event, ui) {
				    var frame = $(this);
				    var uid = frame.attr("id");

				    //default close (firefox) - clear response
				    if (event && event.originalTarget && event.originalTarget.nodeName && event.originalTarget.nodeName == "SPAN")
				        $.FrameDialog.clearResult(uid);

				    //default close (IE7) - clear response
				    if (event && event.originalEvent && event.originalEvent.currentTarget && event.originalEvent.currentTarget.tagName && event.originalEvent.currentTarget.tagName == "A")
				        $.FrameDialog.clearResult(uid);

				    //get the response value, attach to the object.
				    var result = $.FrameDialog._results[uid] || null; //result or an explicit null

				    return result;
				})

				.bind('dialogclose', function(event, ui) {
				    var frame = $(this);
				    var uid = frame.attr("id");
				    var result = $.FrameDialog._results[uid] || null; //result or an explicit null
				    frame.attr("result", result);

				    //Cleanup remnants in 15 seconds
				    //		Should be enough time for the results of the close to finish up.
				    window.setTimeout(
						function() {
						    frame.find("iframe").remove();

						    try { frame.dialog('destroy').remove(); } catch (err) { }
						    //frame.find("div[id='" + uid + "-overlay']").remove();
						    ret.remove();
						    try {
						        delete $.FrameDialog._results[uid];
						    } catch (err) { /*nothing to delete*/ }
						},
						100
					);

				    return result;
				})
				.dialog(opts)
				;

            currentDialog = ret;
            /*** BEGIN FIX FOR jQueryUI 1.7 Dialog's sizing bug *************************************************/
            //store the window width at the start
            var winw = $(document).width();
            var wrap = ret.parent(".ui-resizable")

            //set the window to the appropriate size - fix bug with jQueryUI's Dialog
            //	uses an overlay over the iframe, to prevent focus change.
            wrap.css('width', (opts.minWidth || opts.width || 200) + 'px')
					.css('height', (opts.minHeight || opts.height || 120) + 'px')
					.bind('dragstart', function() {
					    overlay.show();
					})
					.bind('dragstop', function() {
					    overlay.hide();
					})
					.bind('resizestart', function() {
					    overlay.show();
					})
					.bind('resize', function() {
					    iframe.css('height', ret.height() + 'px')
									.css('width', ret.width() + 'px');
					})
					.bind('resizestop', function() {
					    overlay.hide();
					    iframe.css('height', ret.height() + 'px')
								.css('width', ret.width() + 'px');
					});


            //force resize event.
            window.setTimeout(function() {
                wrap.trigger('resizestop');
            }, 100);

            //get window's new width
            var ww = wrap.width();

            //reset the center position, if needed
            if (opts.position == 'center' || (opts.position && (opts.position[0] == 'center' || opts.position[1] == 'center'))) {
                var pos = parseInt(parseFloat(winw - ww) / 2);
                if (pos < 0) pos = 0;

                wrap.css('left', pos + 'px');
            }

            //reset right position, as needed
            if (opts.position == 'right' || (opts.position && (opts.position[0] == 'right' || opts.position[1] == 'right'))) {
                var pos = winw - ww - 5; //set to rightmost, - 5 px
                if (pos < 0) pos = 0;

                wrap.css('left', pos + 'px');
            }
            /*** END FIX FOR jQueryUI 1.7 Dialog's sizing bug *************************************************/
            retry = false; //reset the retry state.
            return ret;
        } catch (err) {
            //cleanup any left over ui elements...
            try { ret.dialog('destroy'); } catch (err) { }
            try { ret.remove(); } catch (err) { }
            try { overlay.remove(); } catch (err) { }
            try { iframe.remove(); } catch (err) { }

            //it was a TypeError (seems to be happening with the modal's overlay mask, retry once.
            if (err instanceof TypeError && !retry) {
                retry = true;
                return $.FrameDialog.create(options); //retry once only
            }

            throw err; //rethrow error if something else
        }
    }

    //    //retrieves the uid for the current frame within the parent.
    //    $.FrameDialog._getUid = function() {
    //        //find the current frame within the parent window
    //        if (window.parent && window.parent.frames && window.parent.document && window.parent.document.getElementsByTagName) {
    //            var iframes = window.parent.document.getElementsByTagName("IFRAME");
    //            for (var i = 0; i < iframes.length; i++) {
    //                var id = iframes[i].id || iframes[i].name || i;
    //                if (window.parent.frames[id] == window) {
    //                    return id.replace("-VIEW", "");
    //                }
    //            }
    //        }
    //        return null; //no match
    //    }

    $.FrameDialog._getUid = function() {
        //find the current frame within the parent window
        if (window.parent && window.parent.frames && window.parent.document && window.parent.document.getElementsByTagName) {
            var iframes = window.parent.document.getElementsByTagName("IFRAME");
            for (var i = iframes.length - 1; i >= 0; i--) {
                var id = iframes[i].id || iframes[i].name || i;
                if (id.substr(id.length - 5, 5) == "-VIEW") {
                    return id.replace("-VIEW", "");
                }
            }
        }
        //$.FrameDialog._isActive = false;
        return null; //no match
    }

    //Returns the current dialog handle in the parent window as a jquery object.
    $.FrameDialog.current = function() {
        if (window.parent && window.parent.jQuery)
            return window.parent.jQuery("#" + $.FrameDialog._getUid());

        return null;
    }


    //clear the result value
    //	uid - id for child window, or empty for current in parent.
    $.FrameDialog.clearResult = function(uid) {
        if (uid) {
            //clear child's value
            try {
                delete $.FrameDialog._results[uid];
            } catch (err) { /*nothing to delete*/ }
        } else {
            //clear for current dialog
            var uid = $.FrameDialog._getUid();

            if (uid != null && window.parent && window.parent.jQuery && window.parent.jQuery.FrameDialog && window.parent.jQuery.FrameDialog._results) {
                try {
                    delete window.parent.jQuery.FrameDialog._results[uid];
                } catch (err) { /*nothing to delete*/ }
            }
        }
    }

    //helper function to set response value	to the parent
    //	value - result value for the given FrameDialog
    //	uid - child id, or empty for current FrameDialog
    $.FrameDialog.setResult = function(value, uid) {
        if (uid) {
            //set child value
            jQuery.FrameDialog._results[uid] = value;
        } else {
            //set value from inside
            var uid = $.FrameDialog._getUid();

            if (uid != null && window.parent && window.parent.jQuery && window.parent.jQuery.FrameDialog && window.parent.jQuery.FrameDialog._results) {
                window.parent.jQuery.FrameDialog._results[uid] = value;
            }
        }
    }

    //same as clicking OK button
    //	uuid - for a child node, or empty for current
    $.FrameDialog.closeDialog = function(uid) {
        if (uid) {
            jQuery("#" + uid).dialog('close');
        } else {
            var uid = $.FrameDialog._getUid();
            if (uid != null && window.parent && window.parent.jQuery) {
                top.jQuery("#" + uid).dialog('close');
            }
        }
        return false;
    }

    //same as clicking Cancel button
    //	uid - for a child node, or empty for current frame
    $.FrameDialog.cancelDialog = function(uid) {
        $.FrameDialog.clearResult(uid);
        $.FrameDialog.closeDialog(uid);
        return false;
    }




    //extension methods for shortcuts in dealing with a framedialog handle
    $.fn.setResult = function(result) {
        return this.each(function() {
            $.FrameDialog.setResult(result, $(this).attr("id"));
        });
    }

    $.fn.clearResult = function() {
        return this.each(function() {
            $.FrameDialog.clearResult($(this).attr("id"));
        });
    }

    $.fn.closeDialog = function() {
        return this.dialog('close');
    }

    $.fn.cancelDialog = function() {
        return this.clearResult().closeDialog();
    }

    //get the window context for the object/iframe in question
    $.fn.window = function() {
        //this item is a frame or iframe
        if (this.attr('tagName') == "IFRAME" || this.attr('tagName') == "FRAME")
            return window.frames[this.attr('name') || this.attr('id')];

        //get the first frame/iframe child
        var frame = this.find('iframe, frame')[0];
        return (frame && window.frames[frame.name || frame.id]) || null;
    }

})(jQuery);
