/*

Siesta 5.1.0
Copyright(c) 2009-2018 Bryntum AB
https://bryntum.com/contact
https://bryntum.com/products/siesta/license

*/
/**
@class Siesta.Test.Browser.Role.CanGetElementFromPoint

*/
Role('Siesta.Test.Browser.Role.CanGetElementFromPoint', {

    requires    : [
        '$'
    ],

    does        : [
        Siesta.Util.Role.CanCalculatePageScroll
    ],

    has : {
    },

    methods : {

        /**
         * This method will return the top-most DOM element at the specified coordinates from the test page. If
         * the resulting element is an iframe and `shallow` argument is not passed as `true`
         * it'll query the iframe for its element from the local point inside it.
         *
         * @param {Number} x The X coordinate, relative to the viewport area (currently visible part of the page)
         * @param {Number} y The Y coordinate, relative to the viewport area (currently visible part of the page)
         * @param {Boolean} [shallow] Pass `true` to _not_ check the nested iframe if element at original coordinates is an iframe.
         *
         * @return {HTMLElement} The top-most element at the specified position on the test page
         */
        elementFromPoint : function (viewportX, viewportY, shallow, fallbackEl, fullInfo) {
            var document    = this.global.document;
            var el          = document.elementFromPoint(viewportX, viewportY)

            // trying 2nd time if 1st attempt failed and returned null
            // this weird thing seems to be required sometimes for IE8 and may be for IE10
            if (!el) el     = document.elementFromPoint(viewportX, viewportY)

            // final fallback to the provided element or to the <body> element
            el              = el || fallbackEl || document.body;

            var localX      = viewportX
            var localY      = viewportY

            // If we found IFRAME and its not a `shallow` request, try to dig deeper
            if (el && el.nodeName.toUpperCase() == 'IFRAME' && !shallow) {
                // if found iframe is loaded from different domain
                // just accessing its "el.contentWindow.document" property will throw exception
                try {
                    var iframeDoc       = el.contentWindow.document;
                    var offsetsToTop    = this.$(el).offset();

                    localX              = viewportX - this.pageXtoViewportX(offsetsToTop.left)
                    localY              = viewportY - this.pageYtoViewportY(offsetsToTop.top)

                    var resolvedEl      = iframeDoc.elementFromPoint(localX, localY)

                    // again weird 2nd attempt for IE
                    if (!resolvedEl) resolvedEl = iframeDoc.elementFromPoint(localX, localY)

                    resolvedEl          = resolvedEl || iframeDoc.body;

                    // Chrome reports 'HTML' in nested document.elementFromPoint calls which makes no sense
                    if (resolvedEl.nodeName.toUpperCase() === 'HTML') resolvedEl = iframeDoc.body;

                    el                  = resolvedEl;
                } catch (e) {
                    // digging deeper failed, restore the local coordinates
                    localX              = viewportX
                    localY              = viewportY
                }
            }

            return fullInfo ? {
                el          : el,
                // viewport coords in the inner frame
                localXY     : [ localX, localY ],
                // viewport coords in the top frame (seems not needed, as just the input values are reused)
                globalXY    : [ viewportX, viewportY ]
            } : el
        }
    }
});