define([], function(){

    function isObject(o)
    {
        return o !== null && typeof o === 'object';
    }

    var itemCmp = function(oldVal, newVal)
    {
        if(Array.isArray(oldVal) && Array.isArray(newVal))
            return arrayCmp(oldVal, newVal);
        else if(isObject(oldVal) && isObject(newVal))
            return objCmp(oldVal, newVal);
        else
            return oldVal === newVal;
    };

    function arrayCmp(oldVal, newVal)
    {
        match = false;

        if(oldVal.length === newVal.length)
        {
            match = true;
            for(var i = 0; i < oldVal.length; ++i)
            {
                match = match && itemCmp(oldVal[i], newVal[i]);
                if(!match)
                    break;
            }
        }

        return match;
    }

    function objCmp(oldVal, newVal)
    {
        oldKeys = Object.keys(oldVal);
        newKeys = Object.keys(newVal);
        oldKeysDiff = Object.keys(oldVal).filter(function(elem){
            return newKeys.indexOf(elem) < 0;
        });
        newKeysDiff = Object.keys(newVal).filter(function(elem){
            return oldKeys.indexOf(elem) < 0;
        });
        match = false;

        if(oldKeysDiff.length === 0 && newKeysDiff.length === 0)
        {
            match = true;
            for(var prop in oldVal)
            {
                if(oldVal.hasOwnProperty(prop))
                {
                    match = match && itemCmp(oldVal[prop], newVal[prop]);
                    if(!match)
                        break;
                }
            }
        }

        return match;
    }

    return itemCmp;
});