import { getEl } from './util.js';
import { doUnmount } from './unmount.js';

const hookNames = ['onmount', 'onunmount'];
const shadowRootAvailable = typeof window !== 'undefined' && 'ShadowRoot' in window;

export const mount = (parent, child, before) => {
  const parentEl = getEl(parent);
  let childEl = getEl(child);

  if (child === childEl && childEl.__redom_view) {
    // try to look up the view if not provided
    child = childEl.__redom_view;
  }

  if (child !== childEl) {
    childEl.__redom_view = child;
  }

  const wasMounted = childEl.__redom_mounted;
  const oldParent = childEl.parentNode;

  if (wasMounted && (oldParent !== parentEl)) {
    doUnmount(child, childEl, oldParent);
  }

  if (before != null) {
    parentEl.insertBefore(childEl, getEl(before));
  } else {
    parentEl.appendChild(childEl);
  }

  doMount(child, childEl, parentEl, oldParent);

  return child;
};

const doMount = (child, childEl, parentEl, oldParent) => {
  const hooks = childEl.__redom_lifecycle || (childEl.__redom_lifecycle = {});
  const remount = (parentEl === oldParent);
  let hooksFound = false;

  for (let i = 0; i < hookNames.length; i++) {
    const hookName = hookNames[i];

    if (!remount && (child !== childEl) && (hookName in child)) {
      hooks[hookName] = (hooks[hookName] || 0) + 1;
    }
    if (hooks[hookName]) {
      hooksFound = true;
    }
  }

  if (!hooksFound) {
    childEl.__redom_mounted = true;
    return;
  }

  let traverse = parentEl;
  let triggered = false;

  if (remount || (!triggered && (traverse && traverse.__redom_mounted))) {
    trigger(childEl, remount ? 'onremount' : 'onmount');
    triggered = true;
  }

  if (remount) {
    return;
  }

  while (traverse) {
    const parent = traverse.parentNode;
    const parentHooks = traverse.__redom_lifecycle || (traverse.__redom_lifecycle = {});

    for (const hook in hooks) {
      parentHooks[hook] = (parentHooks[hook] || 0) + hooks[hook];
    }

    if (!triggered && (traverse === document || (shadowRootAvailable && (traverse instanceof window.ShadowRoot)) || (parent && parent.__redom_mounted))) {
      trigger(traverse, remount ? 'onremount' : 'onmount');
      triggered = true;
    }

    traverse = parent;
  }
};

export const trigger = (el, eventName) => {
  if (eventName === 'onmount') {
    el.__redom_mounted = true;
  } else if (eventName === 'onunmount') {
    el.__redom_mounted = false;
  }

  const hooks = el.__redom_lifecycle;

  if (!hooks) {
    return;
  }

  const view = el.__redom_view;
  let hookCount = 0;

  view && view[eventName] && view[eventName]();

  for (const hook in hooks) {
    if (hook) {
      hookCount++;
    }
  }

  if (hookCount) {
    let traverse = el.firstChild;

    while (traverse) {
      const next = traverse.nextSibling;

      trigger(traverse, eventName);

      traverse = next;
    }
  }
};

@@ -100,16 +100,29 @@
 nmount',
+ 'onremount',
  'onunmo
@@ -1129,52 +1129,8 @@
 or (
-let i = 0; i %3C hookNames.length; i++) %7B%0A    
 cons
@@ -1140,17 +1140,18 @@
 ookName 
-=
+of
  hookNam
@@ -1156,13 +1156,11 @@
 ames
-%5Bi%5D;%0A
+) %7B
 %0A   
@@ -1176,34 +1176,132 @@
 ount
- && (child !== childEl) &&
+) %7B // if already mounted, skip this phase%0A      if (child !== childEl) %7B // only Views can have lifecycle events%0A        if
  (ho
@@ -1316,20 +1316,23 @@
 n child)
-)
  %7B%0A
+    
       ho
@@ -1375,16 +1375,34 @@
 0) + 1;%0A
+        %7D%0A      %7D%0A
     %7D%0A  
@@ -1605,31 +1605,16 @@
 mount %7C%7C
- (!triggered &&
  (traver
@@ -1641,25 +1641,24 @@
 om_mounted))
-)
  %7B%0A    trigg
@@ -1736,42 +1736,8 @@
  %7D%0A%0A
-  if (remount) %7B%0A    return;%0A  %7D%0A%0A
   wh
@@ -1996,17 +1996,16 @@
     if (
-!
 triggere
@@ -2005,19 +2005,54 @@
 riggered
- &&
+) %7B%0A      break;%0A    %7D else %7B%0A      if
  (traver
@@ -2069,16 +2069,24 @@
 ument %7C%7C
+%0A       
  (shadow
@@ -2145,16 +2145,24 @@
 oot)) %7C%7C
+%0A       
  (parent
@@ -2188,21 +2188,29 @@
 mounted)
-)
+%0A      
 ) %7B%0A
+  
       tr
@@ -2257,24 +2257,26 @@
 'onmount');%0A
+  
       trigge
@@ -2287,27 +2287,30 @@
 = true;%0A    
-%7D%0A%0A
+  %7D%0A  
     traverse
@@ -2320,16 +2320,22 @@
 parent;%0A
+    %7D%0A
   %7D%0A%7D;%0A%0A
@@ -2403,24 +2403,53 @@
 == 'onmount'
+ %7C%7C eventName === 'onremount'
 ) %7B%0A    el._

Fix onremount issue, optimize placing hooks