import {List, Map, isImmutable} from 'immutable'

export const DEL = '__DEL__'
export const OVERWRITE = '__OVERWRITE__'

export default function merger(a, b) {
  if (b && (b[OVERWRITE] || (isImmutable(b) && b.get(OVERWRITE)))) {
    if (isImmutable(b)) b = b.delete(OVERWRITE)
    else delete b[OVERWRITE]
    return b
  }

  if (a && b && (Map.isMap(a) || (!isImmutable(a) && typeof a === 'object' && Map.isMap(b)) || (!isImmutable(b) && typeof b === 'object'))) {
    (isImmutable(b) ? b.entrySeq() : Object.entries(b)).forEach(([k, v]) => {
      if (v === DEL) {
        if (isImmutable(b)) b = b.delete(k)
        else delete b[k]
        if (isImmutable(a)) a = a.delete(k)
        else delete a[k]
      }
    })
  }

  if (a && a.mergeWith && !List.isList(a) && b !== null) {
    return a.mergeWith(merger, b)
  }
  return b
}

@@ -118,59 +118,587 @@
 _'%0A%0A
-export default function merger(a, b) %7B%0A  if (b && (
+// https://stackoverflow.com/questions/5876332/how-can-i-differentiate-between-an-object-literal-other-javascript-objects/5878101#5878101%0Afunction isPlainObject(obj) %7B%0A  if (typeof obj == 'object' && obj !== null) %7B%0A    if (typeof Object.getPrototypeOf == 'function') %7B%0A      var proto = Object.getPrototypeOf(obj);%0A      return proto === Object.prototype %7C%7C proto === null;%0A    %7D%0A    return Object.prototype.toString.call(obj) == '%5Bobject Object%5D';%0A  %7D%0A  return false;%0A%7D%0A%0Aexport default function merger(a, b) %7B%0A  // Overwrite handling OVERWRITE%0A  if (b && ((isPlainObject(b) && 
 b%5BOV
@@ -705,16 +705,17 @@
 ERWRITE%5D
+)
  %7C%7C (isI
@@ -852,18 +852,40 @@
 %0A%0A  
+// Deletion handling DEL%0A  
 if (a
- && b
  && 
@@ -905,53 +905,35 @@
  %7C%7C 
-(!isImmutable
+isPlainObject
 (a)
+)
  && 
-typeof a === 'object'
+b
  && 
+(
 Map.
@@ -944,54 +944,27 @@
 p(b)
-)
  %7C%7C 
-(!isImmutable(b) && typeof b === 'o
+isPlainO
 bject
-'
+(b
 ))) 
@@ -1224,16 +1224,35 @@
 %7D)%0A  %7D%0A%0A
+  // Regular merge%0A
   if (a 
@@ -1290,32 +1290,70 @@
 a) && b !== null
+ && (Map.isMap(b) %7C%7C isPlainObject(b))
 ) %7B%0A    return a

fix issue with edge case merges