var assign = make_assign();
var create = make_create();
var trim = make_trim();
var Global = (typeof window !== 'undefined' ? window : global);
module.exports = {
    assign: assign,
    create: create,
    trim: trim,
    bind: bind,
    slice: slice,
    each: each,
    map: map,
    pluck: pluck,
    isList: isList,
    isFunction: isFunction,
    isObject: isObject,
    Global: Global,
};
function make_assign() {
    if (Object.assign) {
        return Object.assign
    } else {
        return function shimAssign(obj, props1, props2, etc) {
            for (var i = 1; i < arguments.length; i++) {
                each(Object(arguments[i]), function (val, key) {
                    obj[key] = val
                })
            }
            return obj
        }
    }
}

function make_create() {
    if (Object.create) {
        return function create(obj, assignProps1, assignProps2, etc) {
            var assignArgsList = slice(arguments, 1);
            return assign.apply(this, [Object.create(obj)].concat(assignArgsList))
        }
    } else {
        function F() {
        } // eslint-disable-line no-inner-declarations
        return function create(obj, assignProps1, assignProps2, etc) {
            var assignArgsList = slice(arguments, 1);
            F.prototype = obj;
            return assign.apply(this, [new F()].concat(assignArgsList))
        }
    }
}

function make_trim() {
    if (String.prototype.trim) {
        return function trim(str) {
            return String.prototype.trim.call(str)
        }
    } else {
        return function trim(str) {
            return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '')
        }
    }
}

function bind(obj, fn) {
    return function () {
        return fn.apply(obj, Array.prototype.slice.call(arguments, 0))
    }
}

function slice(arr, index) {
    return Array.prototype.slice.call(arr, index || 0)
}

function each(obj, fn) {
    pluck(obj, function (key, val) {
        fn(key, val);
        return false
    })
}

function map(obj, fn) {
    var res = (isList(obj) ? [] : {});
    pluck(obj, function (v, k) {
        res[k] = fn(v, k);
        return false
    });
    return res
}

function pluck(obj, fn) {
    if (isList(obj)) {
        for (var i = 0; i < obj.length; i++) {
            if (fn(obj[i], i)) {
                return obj[i]
            }
        }
    } else {
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                if (fn(obj[key], key)) {
                    return obj[key]
                }
            }
        }
    }
}

function isList(val) {
    return (val != null && typeof val != 'function' && typeof val.length == 'number')
}

function isFunction(val) {
    return val && {}.toString.call(val) === '[object Function]'
}

function isObject(val) {
    return val && {}.toString.call(val) === '[object Object]'
}
