/**
 * Copyright 2013 Basarat Ali Syed. All Rights Reserved.
 * Licensed under MIT open source license http://opensource.org/licenses/MIT
 * Original javascript code was by Mauricio Santos
  */

import {ICompareFunction, IEqualsFunction} from '@mezzy/function-types';

/**
 * Dependencies:
 *
 * ICompareFunction
 */
export class CollectionTools {
    /**
     * Default function to compare element order.
     */
    static defaultCompare<T>(a:T, b:T):number {
        if (a < b) return -1;
        else if (a === b) return 0;
        else return 1;
    }


    /**
     * Default function to test equality.
     */
    static defaultEquals<T>(a:T, b:T):boolean { return a === b; }


    /**
     * Default function to convert an object to a string.
     */
    static defaultToString(item:any):string {
        if (item === null) return 'COLLECTION_NULL';
        else if (CollectionTools.isUndefined(item)) return 'COLLECTION_UNDEFINED';
        else if (CollectionTools.isString(item)) return item;
        else return item.toString();
    }


    /**
     * Joins all the properies of the object using the provided join string
     */
    static makeString<T>(item:T, join:string = ","):string {
        if (item === null) return 'COLLECTION_NULL';
        else if (CollectionTools.isUndefined(item)) return 'COLLECTION_UNDEFINED';
        else if (CollectionTools.isString(item)) return item.toString();
        else {
            let toret = "{";
            let first = true;
            for (let prop in item) {
                if (item.hasOwnProperty(prop)) {
                    if (first) first = false;
                    else toret = toret + join;

                    toret = toret + prop + ":" + item[prop];
                }
            }
            return toret + "}";
        }
    }


    /**
     * Checks if the given argument is a function.
     */
    static isFunction(func:any):boolean { return (typeof func) === 'function'; }


    /**
     * Checks if the given argument is undefined.
     */
    static isUndefined(obj:any):boolean { return (typeof obj) === 'undefined'; }


    /**
     * Checks if the given argument is a string.
     */
    static isString(obj:any):boolean { return Object.prototype.toString.call(obj) === '[object String]'; }


    /**
     * Reverses a compare function.
     */
    static reverseCompareFunction<T>(compareFunction:ICompareFunction<T>):ICompareFunction<T> {
        if (!CollectionTools.isFunction(compareFunction)) {
            return function (a, b) {
                if (a < b) return 1;
                else if (a === b) return 0;
                else return -1;
            };
        } else return function (d:T, v:T) { return compareFunction(d, v) * -1; };
    }


    /**
     * Returns an equal function given a compare function.
     */
    static compareToEquals<T>(compareFunction:ICompareFunction<T>):IEqualsFunction<T> {
        return function (a:T, b:T) { return compareFunction(a, b) === 0;  };
    }
} // End class


export default CollectionTools;
