'use strict';

var keysShim; if (!Object.keys) {

// modified from https://github.com/es-shims/es5-shim
var has = Object.prototype.hasOwnProperty;
var toStr = Object.prototype.toString;
var isArgs = require('./isArguments'); // eslint-disable-line global-require
var isEnumerable = Object.prototype.propertyIsEnumerable;
var hasDontEnumBug = !isEnumerable.call({ toString: null }, 'toString');
var hasProtoEnumBug = isEnumerable.call(function () {}, 'prototype');
var dontEnums = [
        'toString',
        'toLocaleString',
        'valueOf',
        'hasOwnProperty',
        'isPrototypeOf',
        'propertyIsEnumerable',
        'constructor'
];
var equalsConstructorPrototype = function (o) {
        var ctor = o.constructor;
        return ctor && ctor.prototype === o;
};
var excludedKeys = {
        $applicationCache: true,
        $console: true,
        $external: true,
        $frame: true,
        $frameElement: true,
        $frames: true,
        $innerHeight: true,
        $innerWidth: true,
        $onmozfullscreenchange: true,
        $onmozfullscreenerror: true,
        $outerHeight: true,
        $outerWidth: true,
        $pageXOffset: true,
        $pageYOffset: true,
        $parent: true,
        $scrollLeft: true,
        $scrollTop: true,
        $scrollX: true,
        $scrollY: true,
        $self: true,
        $webkitIndexedDB: true,
        $webkitStorageInfo: true,
        $window: true
};
var hasAutomationEqualityBug = (function () {
        /* global window */
        if (typeof window === 'undefined') { return false; }
        for (var k in window) {
                try {
                        if (!excludedKeys['$' + k] && has.call(window, k) && window[k] !== null && typeof window[k] === 'object') {
                                try {
                                        equalsConstructorPrototype(window[k]);
                                } catch (e) {
                                        return true;
                                }
                        }
                } catch (e) {
                        return true;
                }
        }
        return false;
}());
var equalsConstructorPrototypeIfNotBuggy = function (o) {
        /* global window */
        if (typeof window === 'undefined' || !hasAutomationEqualityBug) {
                return equalsConstructorPrototype(o);
        }
        try {
                return equalsConstructorPrototype(o);
        } catch (e) {
                return false;
        }
};

keysShim = function keys(object) {
        var isObject = object !== null && typeof object === 'object';
        var isFunction = toStr.call(object) === '[object Function]';
        var isArguments = isArgs(object);
        var isString = isObject && toStr.call(object) === '[object String]';
        var theKeys = [];

        if (!isObject && !isFunction && !isArguments) {
                throw new TypeError('Object.keys called on a non-object');
        }

        var skipProto = hasProtoEnumBug && isFunction;
        if (isString && object.length > 0 && !has.call(object, 0)) {
                for (var i = 0; i < object.length; ++i) {
                        theKeys.push(String(i));
                }
        }

        if (isArguments && object.length > 0) {
                for (var j = 0; j < object.length; ++j) {
                        theKeys.push(String(j));
                }
        } else {
                for (var name in object) {
                        if (!(skipProto && name === 'prototype') && has.call(object, name)) {
                                theKeys.push(String(name));
                        }
                }
        }

        if (hasDontEnumBug) {
                var skipConstructor = equalsConstructorPrototypeIfNotBuggy(object);

                for (var k = 0; k < dontEnums.length; ++k) {
                        if (!(skipConstructor && dontEnums[k] === 'constructor') && has.call(object, dontEnums[k])) {
                                theKeys.push(dontEnums[k]);
                        }
                }
        }
        return theKeys;
};

} module.exports = keysShim;