Figment.Import( "Figment.DOM",Figment.getJSRoot() + "_framework/" );
Figment.Import( "Figment.Form",Figment.getJSRoot() + "_framework/" );
Figment.Import( "Figment.EventHandler",Figment.getJSRoot() + "_framework/" );
Figment.Import( "Figment.HashTable",Figment.getJSRoot() + "_framework/" );
Figment.Import('Disney.WDPRO.IBC.Reporting',Figment.getJSRoot()+ 'reporting/');

Figment.Namespace("Disney.WDPRO.IBC.GuestServices");

/**
 * The following assumptions will be made regarding the HTML structure of the
 * page:
 *
 *  - The Guest Services module WILL have:
 *      »   a css class called "guest_services_module_container"
 *          (this class can be changed via the CONSTANTS)
 *
 *  - Each plug-in container WILL have:
 *      »   a css class called "guest_services_plugin"
 *          (this class can be changed via the CONSTANTS)
 *
 *      »   an attribute called "plugin-name" that will assign a name to the
 *          plug-in so open calls can specify which modules should show by
 *          default
 *          (this attribute name can be changed via the CONSTANTS)
 *
 *  - Any element that triggers the showing of the Guest Services module WILL
 *    have:
 *      »   an attribute called "plugins" that is a comma-delimited list of
 *          the plug-ins that should show by default
 *          (this attribute name can be changed via the CONSTANTS)
 *
 *  - Any element that triggers the showing of the Guest Services module CAN
 *    have:
 *      »   an attribute called "plugin-init-states" that is a comma-delimited
 *          list of the plug-ins' initialization state that should show by
 *          default. This takes precedence over the DEFAULT_STATE of the
 *          plugin.The order is important as each index of this list aligns
 *          with the index of the "plugins" list.  If there is no match, the
 *          DEFAULT_STATE will be used instead.
 *          (this attribute name can be changed via the CONSTANTS)
 *
 *
 * Each plug-in must:
 *
 *  - Have an attribute called "plugin-name" added to the overall container for
 *    the plugin.  The value of this attribute is what should be referenced by
 *    elements triggering the showing of Guest Services in the plug-in list
 *    attribute called "plugins".
 *
 *  - Register itself with Guest Services by calling the "registerPlugin"
 *    method.  A plug-in, even though referenced, will not be availabele until
 *    it is registered.
 *
 *  - Have a method called "getPluginElement" that returns the HTML container
 *    element for the plug-in.
 *
 *  - Have a method called "setToDefaultState" that changes the state of the
 *    plug-in to it's default.  This can be overridden to use any custom state
 *    but requires that the plugin have a "setToState" function.
 *
 *  - Have a method called "getClassName" that returns the fully-qualified name
 *    of the plug-in.
 *
 * @author Philip Jarrell
 * @see //p4-wdpro/Projects/Sites/Development/IBCWDWSite/2.2.0/Documentation/Process Flows/Guest Services.vsd
 * @since 2.2
 */
(function() {
    var self = Disney.WDPRO.IBC.GuestServices;

    self.CONSTANTS = {
        SECURE_SITE_URL:"",
        GUEST_SERVICES_SECURE_WORKFLOW_NAME:"Guest_STD_LoginReg_Guest_Information_WorkFlow",
        DEFAULT_FORM_NAME:"columnCenter_Form",
        GUEST_SERVICES_CONTAINER_CLASS: "guest_services_module_container",
        GUEST_SERVICES_PLUGIN_CLASS: "guest_services_plugin",

        CALLER_ELEMENT_PLUGIN_ATTRIBUTE_NAME: "plugins",
        CALLER_ELEMENT_PLUGIN_INIT_STATES_NAME: "plugin-init-states",
        PLUGIN_NAME_ATTRIBUTE_NAME: "plugin-name",
        STATE_ATTRIBUTE_NAME: "plugin-state",

        SHOW_MODULE_CLASS: "openedState",
        HIDE_MODULE_CLASS: "closedState",

        ERRORS_LIST_CLASS: "guest_services_error_list",
        PREVENT_ASYNC_FROM_PLEASEWAIT: "noAsync",
        PROCESS_ENGINE: "",
        SELECT_FIELD_CLASS: "guest_services_birthday",
        SELECT_HIDE_CLASS: "guest_services_hide"
    };

    self.mapLoginHBXPNCodes= null;
    self.mapLoginHBXMLCCodes= null;
    self.mapLoginSCPNCodes= null;
    self.mapLoginSCHierCodes= null;

    self.strHBXCustom5Variable= null;
    self.strHBXCustom7Variable= null;
    self.strHBXCustom8Variable= null;

    self._observable= null;

    self._debug= false;

    self._plugin_mapping= null;

    self._sourceName= null;

    self._errors= [];

    self.addError= function(errorCode, message)
    {
        self._errors[errorCode] = message;
    };

    self.getError= function(errorCode)
    {
        return self._errors[errorCode];
    };

    self.getSourceName= function()
    {
        return self._sourceName;
    };

    self.setSourceName= function(sourceName)
    {
        self._sourceName = sourceName;
    };

    self.getClassName= function()
    {
        return "Disney.WDPRO.IBC.GuestServices";
    };

    self.registerPlugin= function(plugin)
    {
        var mapping = self._plugin_mapping;
        if(mapping === null)
        {
            mapping = new Figment.HashTable();
        }
        var pluginElement = plugin.getPluginElement();
        if(pluginElement !== null)
        {
            var pluginName = pluginElement.getAttribute(self.CONSTANTS.PLUGIN_NAME_ATTRIBUTE_NAME);
            if(self.Shared.isNotEmptyOrNull(pluginName))
            {
                self.Shared.logger.debug("Registering plug-in: " + pluginName + " with: " + pluginElement.id);
                mapping.put(pluginName, plugin);
                self._plugin_mapping = mapping;
            }
        }
    };

    self.open= function(callerElement, sourceName, state)
    {
        //disable inline functionality for non-secure pages
        if(!Figment.isSecure())
        {
              /*To reduce overconfiguration, we will assume the following unless overridden
                 -Will post to the specified workflow defined in CONSTANTS.GUEST_SERVICES_SECURE_WORKFLOW_NAME
                 -Will set the default completeAction to "return"
                 -If no form was passed (preventing submission), the form specified in CONSTANTS.DEFAULT_FORM_NAME will be used
              */
              var form;
              var workFlowNameInput ={type:"hidden", name:"workflow", value:self.CONSTANTS.GUEST_SERVICES_SECURE_WORKFLOW_NAME};
              var completeActionInput ={type:"hidden",name:"completeAction",value:"return"};

             if(!state || !state.form)
             {
                form = document.getElementById(self.CONSTANTS.DEFAULT_FORM_NAME);

                if(form)
                {
                  form.action = self.CONSTANTS.SECURE_SITE_URL;
                  form.method="post";
                  //set defaults to be submitted and submit
                  Figment.Form.addInputsToForm(form, [
                                                      workFlowNameInput,
                                                      completeActionInput
                                                      ]);

                  form.submit();
                }
             }else if (state) {
             //if form data was provided we will do a post to process engine with the form's data
                if (state.form) {
                     /*even though form data was passed, we will still set the defualts. The defualts
                      * could be overridden by simply specifying them in the state's input variable (state.inputs)
                      */
                     state.form.action = self.CONSTANTS.SECURE_SITE_URL;
                     state.form.method="post";
                     Figment.Form.addInputsToForm(state.form,[workFlowNameInput,
                                                              completeActionInput
                                                              ]);
                    if (state.inputs) {
                        Figment.Form.addInputsToForm(state.form, state.inputs);
                    }
                    state.form.submit();
                }
             }
        }
        else{
            self.setSourceName(sourceName);
            var moduleContainers = Figment.DOM.getElementsByClassName(self.CONSTANTS.GUEST_SERVICES_CONTAINER_CLASS);
            var moduleContainer = moduleContainers.length > 0 ? moduleContainers[0] : null;
            if(moduleContainer !== null)
            {
                var plugin = null;
                var i;

                // Hide all the plugins inside the container right now
                var plugins = Figment.DOM.getElementsByClassName(self.CONSTANTS.GUEST_SERVICES_PLUGIN_CLASS, moduleContainer);
                var len = plugins.length;
                for(i=0; i < len; i++)
                {
                    plugin = plugins[i];
                    // Hide the plugin.  We will later reshow the plugins that
                    // are required by the caller element.
                    Figment.DOM.replaceClassName(plugin, self.CONSTANTS.SHOW_MODULE_CLASS, self.CONSTANTS.HIDE_MODULE_CLASS);
                }

                // Get the list of plugins that should display for this caller
                // element in Guest Services.
                var pluginNames = callerElement.getAttribute(self.CONSTANTS.CALLER_ELEMENT_PLUGIN_ATTRIBUTE_NAME);
                if(pluginNames !== null)
                {
                    var mapping = self._plugin_mapping;
                    if(mapping !== null)
                    {
                        // Get any initialization states for the plugins.
                        var pluginInitStatesList = [];
                        var pluginInitStates = callerElement.getAttribute(self.CONSTANTS.CALLER_ELEMENT_PLUGIN_INIT_STATES_NAME);
                        if(pluginInitStates !== null) {
                            pluginInitStatesList = pluginInitStates.split(',');
                        }

                        var pluginNameList = pluginNames.split(',');
                        len = pluginNameList.length;
                        for(i=0; i < len; i++)
                        {
                            var pluginName = pluginNameList[i].trim();
                            self.Shared.logger.debug("Show plug-in: " + pluginName);

                            var pluginInitState;
                            if(pluginInitStatesList.length > i) {
                                pluginInitState = pluginInitStatesList[i].trim();
                                self.Shared.logger.debug("Plug-in's Init State: " + pluginInitState);
                            }

                            // Get the associated plugin from the DOM
                            plugin = mapping.get(pluginName);
                            if(typeof plugin !== "undefined" && plugin !== null)
                            {
                                // Reset the plug-in's state
                                if(pluginInitState !== undefined) {
                                    // Reset the plugin with a custom state
                                    plugin.setToState(pluginInitState);
                                } else {
                                    // Reset the plug-in to it's default state
                                    plugin.setToDefaultState();
                                }

                                var pluginElement = plugin.getPluginElement();
                                if(pluginElement !== null)
                                {
                                    // Make it visible (the container is not yet
                                    // visible, but the module will be visible when
                                    // the container is then made visible).
                                    Figment.DOM.replaceClassName(pluginElement, self.CONSTANTS.HIDE_MODULE_CLASS, self.CONSTANTS.SHOW_MODULE_CLASS);
                                }
                            }
                            delete pluginName;
                            delete pluginInitState;
                        }
                        delete pluginNameList;
                        delete pluginInitStates;
                        delete pluginInitStatesList;
                    }
                    delete mapping;
                }
                delete len;
                delete i;
                delete plugin;
                delete plugins;
                delete pluginNames;

                // Remove all error codes that were present when last show
                self._clearErrors();

                // Temporarily hide selects when in IE (because IE's select boxes
                // are not layerable
                self._hideSelects();

                // Finally let us show the module
                Figment.DOM.replaceClassName(moduleContainer, self.CONSTANTS.HIDE_MODULE_CLASS, self.CONSTANTS.SHOW_MODULE_CLASS);

                // Now let's reposition the module container so it is relative
                // to the caller element.  This means it should appear just below
                // the caller element.
                self._move(moduleContainer, callerElement);
                self._relocate(moduleContainer, callerElement);
            }

            delete moduleContainers;
            delete moduleContainer;
        }
        self._stopFormEvents();
    };

    self.close= function()
    {
        // Show previously hidden selects again
        self._showSelects();

        var moduleContainers = Figment.DOM.getElementsByClassName(self.CONSTANTS.GUEST_SERVICES_CONTAINER_CLASS);
        var moduleContainer = moduleContainers.length > 0 ? moduleContainers[0] : null;
        if(moduleContainer !== null)
        {
            Figment.DOM.replaceClassName(moduleContainer, self.CONSTANTS.SHOW_MODULE_CLASS, self.CONSTANTS.HIDE_MODULE_CLASS);
        }

        self._restoreFormEvents();
    };

    self.subscribe= function(observer)
    {
        return (typeof observer !== "undefined" && observer !== null) ? observer : new Figment.EventHandler.Observer(self._observable);
    };

    self.unsubscribe= function(observer)
    {
        self._observable.deleteObserver(observer);
    };

    self.dispatchEvent= function(event)
    {
        self._observable.notifyObservers(event);
    };

    self._hideSelects= function()
    {
        if(document.all)
        {
            // In IE hide all select boxes except those in the guest services
            // module
            var selectBoxes = document.getElementsByTagName("SELECT");
            for(var i=0; i < selectBoxes.length; i++)
            {
                var selectBox = selectBoxes[i];
                if(Figment.DOM.hasClassName(selectBox, self.CONSTANTS.SELECT_FIELD_CLASS) === false)
                {
                    Figment.DOM.addClassName(selectBox, self.CONSTANTS.SELECT_HIDE_CLASS);
                }
            }
        }
    };

    self._showSelects= function()
    {
        // In IE show all select boxes except those in the guest services
        // module
        if(document.all)
        {
            var selectBoxes = document.getElementsByTagName("SELECT");
            for(var i=0; i < selectBoxes.length; i++)
            {
                var selectBox = selectBoxes[i];
                if(Figment.DOM.hasClassName(selectBox, self.CONSTANTS.SELECT_HIDE_CLASS))
                {
                    Figment.DOM.removeClassName(selectBox, self.CONSTANTS.SELECT_HIDE_CLASS);
                }
            }
        }
    };

    self._clearErrors= function()
    {
        self.Shared.logger.debug("Clear all errors");
        var errorLists = Figment.DOM.getElementsByClassName(self.CONSTANTS.ERRORS_LIST_CLASS);
        for(var i=0; i < errorLists.length; i++)
        {
            var errorList = errorLists[i];
            var errorsUL = errorList.getElementsByTagName("UL");
            for(var j=0; j < errorsUL.length; j++)
            {
                var errorUL = errorsUL[j];
                errorList.removeChild(errorUL);
            }
        }
    };

    self.changeState= function(state, stateElements)
    {
        // Remove all error codes that were present when last show
        self._clearErrors();
        self.Shared.logger.debug("Change state to: " + state);
        var statesMap = new Figment.HashTable();
        for(var i=0; i < stateElements.length; i++)
        {
            var stateElement = stateElements[i];
            var stateName = stateElement.getAttribute(self.CONSTANTS.STATE_ATTRIBUTE_NAME);

            if(stateName === state)
            {
                // Turn this state ON
                Figment.DOM.replaceClassName(stateElement, self.CONSTANTS.HIDE_MODULE_CLASS, self.CONSTANTS.SHOW_MODULE_CLASS);
            }
            else
            {
                // Turn this state OFF
                Figment.DOM.replaceClassName(stateElement, self.CONSTANTS.SHOW_MODULE_CLASS, self.CONSTANTS.HIDE_MODULE_CLASS);
            }
        }
    };

    self._stopFormEvents= function()
    {
        self.Shared.logger.debug("Stopping form events temporarily");
        var forms = document.getElementsByTagName("FORM");
        for(var i=0; i < forms.length; i++)
        {
            var formElement = forms[i];
            formElement._onsubmit = formElement.onsubmit;
            formElement.onsubmit = function(event){return false;};
        }
    };

    self._restoreFormEvents= function()
    {
        self.Shared.logger.debug("Restoring form events");
        var forms = document.getElementsByTagName("FORM");
        for(var i=0; i < forms.length; i++)
        {
            var formElement = forms[i];
            formElement.onsubmit = formElement._onsubmit;
            formElement._onsubmit = null;
        }
    };

    self._move= function(element, callerElement)
    {
        // Move the module to be near the callerElement for positioning
        Figment.DOM.insertNodeBefore(element, document.body.firstChild);
        element.style.zIndex = 107242346;
    };

    self._relocate= function(element, callerElement)
    {
        var position;
        var viewport,moduleLocation,callerLocation;
        var parentElement = callerElement.parentNode;

        if( ( typeof callerElement === "undefined" || callerElement === null ) || ( typeof element === "undefined" || element === null ) )
        {
            return;
        }

        // Get the location of the element
        position = self._getPosition(callerElement);

        // IE blows up on offsetHeight & offsetWidth and forces DIV to be
        // unusuable, so lets catch the error
        try {
            moduleLocation = self.Support.getLocation(element);
            callerLocation = self.Support.getLocation(callerElement);
            element.style.top = position.top + (- element.offsetHeight) + "px";
            element.style.left = ( position.left - (element.offsetWidth - callerElement.offsetWidth) ) + "px";
            element.style.position = "absolute";
            viewport = self.Support.getViewPortDimensions();
            moduleLocation = self.Support.getLocation(element);
            if( moduleLocation.x1 < 0 )
            {
                element.style.left = position.left + "px";
            }
            if( moduleLocation.y2 < 0 )
            {
                element.style.top = position.top + "px";
            }
            if( moduleLocation.y2 < callerLocation.y2 )
            {
                element.style.top = position.top + "px";
            }
            if( (element.offsetTop + element.offsetHeight) > viewport.y2 )
            {
                var theTop = 0;
                if( document.documentElement && document.documentElement.scrollTop )
                {
                    theTop = document.documentElement.scrollTop;
                }
                else if( document.body )
                {
                    theTop = document.body.scrollTop;
                }
                window.scrollTo(0, moduleLocation.y1);
            }
        }
        catch (error)
        {
            // Fail silently, DIV is displayed just not relocated
        }
    };

    self._getPosition= function(element)
    {
        var curleft = 0;
        var curtop = 0;
        if( element.offsetParent )
        {
            curleft = element.offsetLeft;
            curtop = element.offsetTop;
            while((element = element.offsetParent)) {
                curleft += element.offsetLeft;
                curtop += element.offsetTop;
            }
        }
        return {"top": curtop, "left": curleft, "toString": function(){return "{top: " + this.top + ", left: " + this.left + "}";}};
    };

    self._closeCallback= function(e)
    {
        var event = Figment.EventHandler.getEvent(e);
        var element = event.element;
        self.close();

        var strHBXPageViewCode = hbx.pn;
        var strHBXMLCCode = hbx.mlc;
        var strSCPNCode = '';
        var strSCHierCode = '';
        if (s_wdpro.hier1 !== null){
            strSCPNCode = s_wdpro.pageName;
            strSCHierCode = s_wdpro.hier1;
        }
        if (strHBXPageViewCode !== null && strHBXMLCCode !== null){
            self.EVENT_HBX_Event_PageView(strHBXPageViewCode,strHBXMLCCode,strSCPNCode,strSCHierCode);
        }
    };

    self.main= function()
    {
        //build secure url value
        var processEnginePath = "/_framework/components/processEngine";
        this.CONSTANTS.SECURE_SITE_URL = Figment.getSecureBase() + Figment.getWebRoot() + Figment.getContentLanguage() + processEnginePath;
        this.CONSTANTS.PROCESS_ENGINE  = Figment.getWebRoot() + Figment.getContentLanguage() + processEnginePath;

        self.strHBXCustom5Variable = cv.c5;
        self.strHBXCustom7Variable = cv.c7;
        self.strHBXCustom8Variable = cv.c8;


        // If hitbox is not defined, fail gracefully
        try {
            Disney.WDPRO.IBC.GuestServices.strHBXCustom5Variable = cv.c5;
            Disney.WDPRO.IBC.GuestServices.strHBXCustom8Variable = cv.c8;
        } catch(e) {}

        self._observable = new Figment.EventHandler.Observable();
        self._debug = self.Shared.getQueryVariable("debug") === "true" ? true : false;
        // This is for browsers that don't have FireBug!
        if(typeof console === "undefined")
        {
            console = {
                debug: function(message)
                {
                    alert(message);
                }
            };
        }
        self.Shared.logger.debug("Loading Guest Services...");
        var closeLink = document.getElementById("guest_services_module_close_link");
        if(closeLink !== null)
        {
            Figment.EventHandler.addEvent(closeLink, "click", self._closeCallback);
        }

        self.mapLoginHBXPNCodes = new Figment.HashTable();
        self.mapLoginHBXMLCCodes = new Figment.HashTable();
        self.mapLoginSCPNCodes = new Figment.HashTable();
        self.mapLoginSCHierCodes = new Figment.HashTable();
    };

    self.EVENT_HBX_Event_PageView= function(strHBXPageViewCode,strHBXMLCCode,strSCPNCode,strSCHierCode){
        /*_hbSet('cv.c5',self.strHBXCustom5Variable);
        _hbSet('cv.c8',self.strHBXCustom8Variable);
        _hbPageView(strHBXPageViewCode,strHBXMLCCode);*/

        //set option object for tracking page views
        var optionsObject = {engines:[Disney.WDPRO.IBC.Reporting.ANALYTICS_ENGINES.HitBox,Disney.WDPRO.IBC.Reporting.ANALYTICS_ENGINES.SiteCatalyst],
                            customVarsName:['cv.c5','cv.c7','cv.c8'],
                            customVarsValue:[self.strHBXCustom5Variable,self.strHBXCustom7Variable,self.strHBXCustom8Variable]
                            };
        optionsObject.pageName = strHBXPageViewCode;
        optionsObject.MLC = strHBXMLCCode;
        optionsObject.scPageName = strSCPNCode;
        optionsObject.hier = strSCHierCode;

        //track link
        Disney.WDPRO.IBC.Reporting.TrackCustomPageView(optionsObject);

        //clean up
        delete optionsObject;
    };

    self.getHBXPNCode= function(windowEvent)
    {
        var objElement = windowEvent.element;

        var strNeedRegisterCode = objElement.id;
        var strHBXPageViewCode = self.mapLoginHBXPNCodes.get(strNeedRegisterCode);
        return strHBXPageViewCode;
    };

    self.getHBXMLCCode= function(windowEvent)
    {
        var objElement = windowEvent.element;

        var strNeedRegisterCode = objElement.id;
        var strHBXMLCCode = self.mapLoginHBXMLCCodes.get(strNeedRegisterCode);
        return strHBXMLCCode;
    };

    self.getSCPNCode= function(windowEvent)
    {
        var objElement = windowEvent.element;

        var strNeedRegisterCode = objElement.id;
        var strSCPNCode = self.mapLoginSCPNCodes.get(strNeedRegisterCode);
        return strSCPNCode;
    };

    self.getSCHierCode= function(windowEvent)
    {
        var objElement = windowEvent.element;

        var strNeedRegisterCode = objElement.id;
        var strSCHierCode = self.mapLoginSCHierCodes.get(strNeedRegisterCode);
        return strSCHierCode;
    };
})();

Disney.WDPRO.IBC.GuestServices.Shared = {

    isNotEmptyOrNull: function(obj)
    {
        return (typeof obj !== "undefined" && obj !== null) ? true : false;
    },

    getQueryVariable: function(variable)
    {
        var queryString = location.search.substring(1);
        var variables = queryString.split("&");
        for( var i=0; i < variables.length; i++ )
        {
            var pair = variables[i].split("=");
            if(pair[0] == variable)
            {
                return pair[1];
            }
        }
        return null;
    },

    logger:
    {
        debug: function(message)
        {
            if(Disney.WDPRO.IBC.GuestServices._debug)
            {
                console.debug(message);
            }
        }
    }

};

Disney.WDPRO.IBC.GuestServices.Event = Figment.Class();
Disney.WDPRO.IBC.GuestServices.Event.prototype = {
    initialize: function()
    {
        this.source = null;
        this.errors = [];
        this.event = null;
        this.data = new Figment.HashTable();
        this.result = false;
    },

    getEvent: function()
    {
        return this.event;
    },

    setEvent: function(event)
    {
        this.event = event;
    },

    getErrors: function()
    {
        return this.errors;
    },

    addError: function(error)
    {
        this.errors.push(error);
    },

    setErrors: function(errors)
    {
        this.errors = errors;
    },

    getSource: function()
    {
        return this.source;
    },

    setSource: function(source)
    {
        this.source = source;
    },

    getData: function()
    {
        return this.data;
    },

    addData: function(key, value)
    {
        this.data.put(key, value);
    },

    setData: function(data)
    {
        this.data = data;
    },

    getResult: function()
    {
        return this.result;
    },

    setResult: function(result)
    {
        this.result = result;
    },

    toString: function()
    {
        return "{event: \"" + this.event + "\", source: \"" + this.source + "\", result: " + this.result + ", errors: " + this.errors.toString() + ", data: " + this.data.toString() + "}";
    }
};

/**
 * Provides support for relocating the Guest Services module to be relative to
 * a caller element.
 */
Disney.WDPRO.IBC.GuestServices.Support = {
    /**
     * Gets the current viewports dimensions as a
     * Disney.WDPRO.IBC.GuestServices.Rect.
     *
     * @return {Disney.WDPRO.IBC.GuestServices.Rect}
     */
    getViewPortDimensions: function()
    {
        var rect = new Disney.WDPRO.IBC.GuestServices.Rect();
        if( document.documentElement && document.documentElement.clientWidth )
        {
            rect.x2 = document.documentElement.clientWidth;
        }
        else if( document.body && document.body.clientWidth )
        {
            rect.x2 = document.body.clientWidth;
        }
        else if( window.innerWidth )
        {
            rect.x2 = window.innerWidth - 18;
        }

        if( document.documentElement && document.documentElement.clientHeight )
        {
            rect.y2 = document.documentElement.clientHeight;
        }
        else if( document.body && document.body.clientHeight )
        {
            rect.y2 = document.body.clientHeight;
        }
        else if( window.innerHeight )
        {
            rect.y2 = window.innerHeight - 18;
        }

        return rect;
    },

    /**
     * Compares two rectangles to determine if the first one is contained
     * within the second one.
     *
     * @param {Disney.WDPRO.IBC.GuestServices.Rect} rect
     * @param {Disney.WDPRO.IBC.GuestServices.Rect} rectCompareTo
     * @return {Boolean}
     */
    isWithinRect: function(rect,rectCompareTo)
    {
        var bCompare = true;
        if( rect.x1 >= rectCompareTo.x1 && rect.x2 <= rectCompareTo.x2 )
        {
            bCompare = true;
        }
        else
        {
            bCompare = false;
        }
        if( bCompare && rect.y1 >= rectCompareTo.y1 && rect.y2 <= rectCompareTo.y2 )
        {
            bCompare = true;
        }
        else
        {
            bCompare = false;
        }

        return bCompare;
    },

    /**
     * Gets the current location of the Guest Services module.
     *
     * @param {IHTMLElement} element
     * @return {Disney.WDPRO.IBC.GuestServices.Rect}
     */
    getLocation: function(element)
    {
        var rect = new Disney.WDPRO.IBC.GuestServices.Rect();
        if( element !== null )
        {
            rect.x1 = Figment.DOM.getX(element);
            rect.x2 = Figment.DOM.getX(element) + element.offsetWidth;
            rect.y1 = Figment.DOM.getY(element);
            rect.y2 = Figment.DOM.getY(element) + element.offsetTop + element.offsetHeight;
        }
        return rect;
    }
};

/**
 * Holds the current coordinates of an element.
 * @constructor
 */
Disney.WDPRO.IBC.GuestServices.Rect = Figment.Class();
Disney.WDPRO.IBC.GuestServices.Rect.prototype = {
    initialize: function()
    {
        this.x1 = 0;
        this.x2 = 0;
        this.y1 = 0;
        this.y2 = 0;
    },

    /**
     * Returns the location of the rectangle.
     *
     * @return {String}
     */
    toString: function()
    {
        return "{x1:" + this.x1 + ",x2:" + this.x2 + ",y1:" + this.y1 + ",y2:" + this.y2 + "}";
    }
};

/*
 *  Add the main method to the registry so it will be called when the DOM is
 *  ready.
 */
Figment.EntryPoint.add(Disney.WDPRO.IBC.GuestServices);
