/* global P2_ARRAY_TYPE */

//都是静态方法
/**
 *  Misc utility functions
 */
export class Utils {

    /**
     * Append the values in array b to the array a. See <a href="http://stackoverflow.com/questions/1374126/how-to-append-an-array-to-an-existing-javascript-array/1374131#1374131">this</a> for an explanation.
     * @method appendArray
     * @static
     * @param  {Array} a
     * @param  {Array} b
     */
    public static appendArray(a, b) {
        if (b.length < 150000) {
            a.push.apply(a, b);
        } else {
            for (var i = 0, len = b.length; i !== len; ++i) {
                a.push(b[i]);
            }
        }
    };

    /**
     * Garbage free Array.splice(). Does not allocate a new array.
     * @method splice
     * @static
     * @param  {Array} array
     * @param  {Number} index
     * @param  {Number} howmany
     */
    public static splice(array: any, index: number, howmany?: number) {
        howmany = howmany || 1;
        for (var i = index, len = array.length - howmany; i < len; i++) {
            array[i] = array[i + howmany];
        }
        array.length = len;
    };

    /**
     * Remove an element from an array, if the array contains the element.
     * @method arrayRemove
     * @static
     * @param  {Array} array
     * @param  {Number} element
     */
    public static arrayRemove(array: any, element: number) {
        var idx = array.indexOf(element);
        if (idx !== -1) {
            Utils.splice(array, idx, 1);
        }
    };

    /**
     * The array type to use for internal numeric computations throughout the library. Float32Array is used if it is available, but falls back on Array. If you want to set array type manually, inject it via the global variable P2_ARRAY_TYPE. See example below.
     * @static
     * @property {function} ARRAY_TYPE
     * @example
     *     <script>
     *         <!-- Inject your preferred array type before loading p2.js -->
     *         P2_ARRAY_TYPE = Array;
     *     </script>
     *     <script src="p2.js"></script>
     */
    // if(typeof P2_ARRAY_TYPE !== 'undefined') {
    //   Utils.ARRAY_TYPE = P2_ARRAY_TYPE;
    // } else if (typeof Float32Array !== 'undefined') {
    public static ARRAY_TYPE = Float32Array;
    // } else {
    //     Utils.ARRAY_TYPE = Array;
    // }

    /**
     * Extend an object with the properties of another
     * @static
     * @method extend
     * @param  {object} a
     * @param  {object} b
     */
    public static extend(a, b) {
        for (var key in b) {
            a[key] = b[key];
        }
    };

    /**
     * Shallow clone an object. Returns a new object instance with the same properties as the input instance.
     * @static
     * @method shallowClone
     * @param  {object} obj
     */
    public static shallowClone(obj) {
        var newObj = {};
        Utils.extend(newObj, obj);
        return newObj;
    };

    /**
     * Extend an options object with default values.
     * @deprecated Not used internally, will be removed.
     * @static
     * @method defaults
     * @param  {object} options The options object. May be falsy: in this case, a new object is created and returned.
     * @param  {object} defaults An object containing default values.
     * @return {object} The modified options object.
     */
    public static defaults(options, defaults) {
        console.warn('Utils.defaults is deprecated.');
        options = options || {};
        for (var key in defaults) {
            if (!(key in options)) {
                options[key] = defaults[key];
            }
        }
        return options;
    }
}
