/*

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

*/
Singleton('Siesta.Project.Browser.FeatureSupport', {

    has     : {
        isConfigured        : false,

        supports    : Joose.I.Object,

        simulator   : {
            lazy        : 'this.buildWebSimulator'
        },

        tests       : {
            init        : [
                {
                    id  : 'TouchEvents',
                    fn  : function() {
                        return this.isEventSupported('touchend', window);
                    }
                },
                {
                    id  : 'PointerEvents',
                    fn  : function () {
                        return Boolean(window.PointerEvent)
                    }
                },
                {
                    id  : 'MSPointerEvents',
                    fn  : function() {
                        return Boolean(window.MSPointerEvent)
                    }
                },
                {
                    id  : 'PointerEventsGeneric',
                    fn  : function () {
                        return Boolean(window.PointerEvent || window.MSPointerEvent)
                    }
                },
                // "fn"s are called as methods of the "Siesta.Project.Browser.FeatureSupport" singleton
                {
                    id : "mouseEnterLeave",
                    fn : function() {
                        var el = document.createElement("div");
                        return 'onmouseenter' in el && 'onmouseleave' in el;
                    }
                },

                {
                    id : "enterOnAnchorTriggersClick",
                    fn : function() {
                        var sim     = this.getSimulator(),
                            E       = Siesta.Test.UserAgent.KeyCodes().keys.ENTER,
                            result  = false;

                        var anchor = $('<a href="foo" style="display:none">test me</a>');
                        $('body').append(anchor);

                        anchor.focus({preventScroll : true});
                        anchor.click(function(e) {
                            result = true;
                            return false;
                        });

                        sim.simulateEvent(anchor, 'keypress', { keyCode : E, charCode : 0 });

                        anchor.remove();
                        return result;
                    }
                },

                {
                    id : "canSimulateKeyCharacters",
                    fn : function() {
                        var sim     = this.getSimulator();

                        var input   = $('<input class="siesta-hidden" type="text" />'),
                            A       = Siesta.Test.UserAgent.KeyCodes().keys.A;

                        $('body').append(input);

                        input.focus({preventScroll : true});
                        sim.simulateEvent(input, 'keypress', { keyCode : A, charCode : A });
                        sim.simulateEvent(input, 'textInput', { text : "A" });

                        var result  = input.val() === 'A';

                        input.remove();

                        return result;
                    }
                },

                {
                    id : "canSimulateBackspace",
                    fn : function() {
                        var sim     = this.getSimulator();

                        var input   = $('<input class="siesta-hidden" type="text" />'),
                            BS      = Siesta.Test.UserAgent.KeyCodes().keys.BACKSPACE,
                            A       = Siesta.Test.UserAgent.KeyCodes().keys.A;

                        $('body').append(input);

                        input.focus({preventScroll : true});
                        sim.simulateEvent(input, 'keypress', { keyCode : A, charCode : A });
                        sim.simulateEvent(input, 'keypress', { keyCode : A, charCode : A });
                        sim.simulateEvent(input, 'keypress', { keyCode : BS, charCode : BS });

                        var result  = input.val() === 'A';

                        input.remove();

                        return result;
                    }
                },

                {
                    id : "enterSubmitsForm",
                    fn : function() {
                        var sim     = this.getSimulator(),
                            E       = Siesta.Test.UserAgent.KeyCodes().keys.ENTER,
                            result  = false;

                        var form = $('<form method="post"><input type="text"/></form>');
                        var input = $(form).find('input');
                        $('body').append(form);

                        form[0].onsubmit = function(e) {
                            result = true;
                            return false;
                        };

                        input.focus({preventScroll : true});
                        sim.simulateEvent(input, 'keypress', { keyCode : E, charCode : 0 });

                        form.remove();
                        return result;
                    }
                },
                // remove after https://bugzilla.mozilla.org/show_bug.cgi?id=959992 will be fixed
                {
                    id : "imageWithIdCreatesGlobalEnumerable",
                    fn : function () {
                        var img     = $('<img id="test_img_id"/>');

                        $('body').append(img);

                        var hasImgId    = false

                        for (var i in window) {
                            if (i == 'test_img_id') hasImgId = true
                        }

                        img.remove();

                        return hasImgId;
                    }
                }
            ]
        }

    },

    methods     : {

        buildWebSimulator : function () {
            return new Siesta.Test.Simulator({
                global  : window,
                test    : {
                    normalizeElement    : function(a) { return a[ 0 ]; }
                }
            });
        },


        configure : function() {
            // Already configured
            if (this.isConfigured) return

            this.isConfigured       = true

            for (var i = 0; i < this.tests.length; i++) {
                var test            = this.tests[i];
                var testId          = test.id;
                var detectorFn      = test.fn;

                try {
                    // also save the results to "results" property - we'll use this in our own test suite
                    // where we copy the feature testing results from the outer scope to inner
                    this.supports[ testId ] = detectorFn.call(this);
                } catch (e) {
                    this.supports[ testId ] = false
                }
            }
        },


        // from Modernizr
        isEventSupported: function (eventName, element) {
            var isSupported;

            if (!eventName) return false
            if (!element || typeof element === 'string') element = document.createElement(element || 'div');

            // Testing via the `in` operator is sufficient for modern browsers and IE.
            // When using `setAttribute`, IE skips "unload", WebKit skips "unload" and
            // "resize", whereas `in` "catches" those.
            eventName       = 'on' + eventName;
            isSupported     = eventName in element;

            // Fallback technique for old Firefox - bit.ly/event-detection
            if (!isSupported) {
                if (!element.setAttribute) {
                    // Switch to generic element if it lacks `setAttribute`.
                    // It could be the `document`, `window`, or something else.
                    element = document.createElement('div');
                }

                element.setAttribute(eventName, '');
                isSupported = typeof element[ eventName ] === 'function';

                if (element[ eventName ] !== undefined ) {
                    // If property was created, "remove it" by setting value to `undefined`.
                    element[ eventName ] = undefined;
                }
                element.removeAttribute(eventName);
            }

            return isSupported;
        }

    }
})