import { isObject, isDate, isArray } from './types.js';

/**
 * Recursive objects equivalence check.
 * @param {*} obj1 The original object.
 * @param {*} obj2 The object to compare
 * @param {Array} [processing] A list of already processed comparisons.
 * @return {Boolean}
 */
export default function equivalent(obj1, obj2, processing = []) {
    if (typeof obj1 === typeof obj2) {
        if (isArray(obj1)) {
            if (obj1.length === obj2.length) {
                for (let i = 0, len = obj1.length; i < len; i++) {
                    if (!equivalent(obj1[i], obj2[i], processing)) {
                        return false;
                    }
                }
                return true;
            }
            return false;
        } else if (isObject(obj1)) {
            let processSourceIndex = processing.indexOf(obj1);
            let processTargetIndex = processing.indexOf(obj2);
            if (processSourceIndex !== -1 && processTargetIndex !== -1 && processSourceIndex % 2 === 1 && processSourceIndex === (processTargetIndex + 1)) {
                return true;
            }
            let sourceKeys = Object.keys(obj1).sort();
            let targetKeys = Object.keys(obj2).sort();
            if (equivalent(sourceKeys, targetKeys)) {
                for (let i = 0, len = sourceKeys.length; i < len; i++) {
                    let key = sourceKeys[i];
                    if (!equivalent(obj1[key], obj2[key], processing)) {
                        return false;
                    }
                }
                return true;
            }
            return false;
        } else if (isDate(obj1)) {
            return obj1.getTime() === obj2.getTime();
        }
        return obj1 === obj2;
    }
    return false;
}

@@ -449,24 +449,71 @@
 2.length) %7B%0A
+                // Arrays have the same length%0A
             
@@ -559,32 +559,32 @@
 i %3C len; i++) %7B%0A
-
                 
@@ -628,32 +628,78 @@
  processing)) %7B%0A
+                        // Deep check failed.%0A
                 
@@ -858,32 +858,86 @@
 Object(obj1)) %7B%0A
+            // handle multiple object instance check.%0A
             let 
@@ -999,59 +999,159 @@
     
-let processTargetIndex = processing.indexOf(obj2);%0A
+while (processSourceIndex !== -1) %7B%0A                // %60processing%60 array contains pairs of compared object, so left objects have always odd index%0A    
     
@@ -1177,29 +1177,32 @@
 SourceIndex 
-!
+%25 2 =
 == 
--
 1 && process
@@ -1205,30 +1205,12 @@
 cess
-TargetIndex !== -1 && 
+ing%5B
 proc
@@ -1228,99 +1228,341 @@
 dex 
-%25 2
++ 1%5D
  === 
-1 && processSourceIndex === (processTargetIndex + 1)) %7B%0A                return true
+obj2) %7B%0A                    // The comparison between the two objects has been already handled before.%0A                    return true;%0A                %7D%0A                // The same object could be compared more than once, so we have to check for all references.%0A                processSourceIndex = processing.indexOf(obj1)
 ;%0A  
@@ -1733,24 +1733,72 @@
 getKeys)) %7B%0A
+                // objects keys are equivalent.%0A
             
@@ -1968,32 +1968,78 @@
  processing)) %7B%0A
+                        // deep check failed.%0A
                 
@@ -2196,27 +2196,132 @@
 isDate(obj1)
-) %7B
+ && isDate(obj2)) %7B%0A            // We cannot compare two dates just using %60===%60, so we use their timestamps.
 %0A           
@@ -2365,32 +2365,58 @@
 me();%0A        %7D%0A
+        // Generic check.%0A
         return o
@@ -2429,22 +2429,78 @@
 = obj2;%0A
-
     %7D%0A
+    // Comparison failed because object types mismatch.%0A
     retu

add some documentation to equivalent method