const {
    hasOwnProperty
} = Object.prototype;

/**
 * Copies values of all enumerable own properties from one or more source
 * objects (provided as extended arguments to the function) to a target object.
 *
 * @param {!Object} target
 * @param {...Object} var_args
 * @return {!Object}
 */
export function assign(target, var_args) {
    if (target == null) {
        throw new TypeError('Cannot convert undefined or null to object');
    }

    const output = Object(target);
    for (let i = 1; i < arguments.length; i++) {
        const source = arguments[i];
        if (source != null) {
            for (const key in source) {
                if (hasOwnProperty.call(source, key)) {
                    output[key] = source[key];
                }
            }
        }
    }
    return output;
}

/**
 * Sets the Object.assign polyfill if it does not exist.
 * @param {!Window} win
 */
export function install(win) {
    if (!win.Object.assign) {
        win.Object.defineProperty(win.Object, 'assign', {
            enumerable: false,
            configurable: true,
            writable: true,
            value: assign,
        });
    }
}