'use strict';

/*@
Ox.extend <function> Extends an object with one or more other objects
    > Ox.extend({a: 1, b: 1, c: 1}, {b: 2, c: 2}, {c: 3})
    {a: 1, b: 2, c: 3}
@*/
Ox.extend = function() {
    var obj = arguments[0];
    Ox.forEach(Array.prototype.slice.call(arguments, 1), function(arg, i) {
        Ox.forEach(arg, function(val, key) {
            obj[key] = val;
        });
    });
    return obj;
};

/*@
Ox.keyOf <f> Equivalent of [].indexOf for objects
    > Ox.keyOf({a: 1, b: 2, c: 3}, 1)
    'a'
@*/
Ox.keyOf = function(obj, val) {
    var key;
    Ox.forEach(obj, function(v, k) {
        if (v == val) {
            key = k;
            return false;
        }
    });
    return key;
};

/*@
Ox.methods <f> Returns a sorted list of all method names of an object
    > Ox.methods({a: [], b: false, f: function() {}, n: 0, o: {}, s: ''})
    ['f']
@*/
Ox.methods = function(obj) {
    return Object.keys(obj).filter(function(key) {
        return Ox.isFunction(obj[key]);
    }).sort();
};

/*@
Ox.serialize <f> Parses an object into query parameters
    > Ox.serialize({a: 1, b: 2, c: 3})
    'a=1&b=2&c=3'
    > Ox.serialize({a: -1, b: 2.3, c: [4, 5]})
    'a=-1&b=2.3&c=4,5'
    > Ox.serialize({string: 'foo', empty: {}, null: null, undefined: void 0})
    'string=foo'
@*/
Ox.serialize = function(obj) {
    var arr = [];
    Ox.forEach(obj, function(val, key) {
        if (!Ox.isEmpty(val) && !Ox.isNull(val) && !Ox.isUndefined(val)) {
            arr.push(key + '=' + val);
        }
    });
    return arr.join('&');
};

/*@
Ox.unserialize <f> Parses query parameters into an object
    > Ox.unserialize('a=1&b=2&c=3')
    {a: '1', b: '2', c: '3'}
    > Ox.unserialize('a=-1&b=2.3&c=4,5', true)
    {a: -1, b: 2.3, c: [4, 5]}
    > Ox.unserialize('a=1&b=&c&a=0', true)
    {a: 0}
@*/
Ox.unserialize = function(str, toNumber) {
    var obj = {};
    Ox.forEach(str.split('&'), function(val) {
        if (val) {
            var arr = val.split('=');
            if (arr[1]) {
                obj[arr[0]] = !toNumber ? arr[1]
                    : arr[1].indexOf(',') == -1 ? +arr[1]
                    : arr[1].split(',').map(function(val) {
                        return +val;
                    });
            }
        }
    });
    return obj;
};