
export function getAnchorViewPosition (scrollElement) {
  if (scrollElement === null) {
    return null
  }
  let anchor = document.getSelection().anchorNode
  if (anchor != null) {
    let top = getBoundingClientRect(anchor).top
    if (top >= 0 && top <= document.documentElement.clientHeight) {
      return {
        anchor: anchor,
        top: top
      }
    }
  }
  return {
    anchor: null,
    scrollTop: scrollElement.scrollTop,
    scrollHeight: scrollElement.scrollHeight
  }
}

// get BoundingClientRect that works on text nodes
function getBoundingClientRect (element) {
  if (element.getBoundingClientRect != null) {
    // is element node
    return element.getBoundingClientRect()
  } else {
    // is text node
    if (element.parentNode == null) {
      // range requires that text nodes have a parent
      let span = document.createElement('span')
      span.appendChild(element)
    }
    let range = document.createRange()
    range.selectNode(element)
    return range.getBoundingClientRect()
  }
}

export function fixScrollPosition (scrollElement, fix, element, multiplicator) {
  if (scrollElement !== null) {
    if (fix.anchor === null) {
      let rect = getBoundingClientRect(element)
      if (rect.top <= 0 && scrollElement.scrollTop === fix.scrollTop) {
        console.log('scrolltop fix')
        scrollElement.scrollTop += scrollElement.scrollHeight - fix.scrollHeight
      }
    } else {
      scrollElement.scrollTop += getBoundingClientRect(fix.anchor).top - fix.top
    }
  }
}

export function defaultDomFilter (node, attributes) {
  return attributes
}

/*
 * 1. Check if any of the nodes was deleted
 * 2. Iterate over the children.
 *    2.1 If a node exists without __yxml property, insert a new node
 *    2.2 If _contents.length < dom.childNodes.length, fill the
 *        rest of _content with childNodes
 *    2.3 If a node was moved, delete it and
 *       recreate a new yxml element that is bound to that node.
 *       You can detect that a node was moved because expectedId
 *       !== actualId in the list
 */
export function applyChangesFromDom (yxml) {
  let undeletedKnownChildren = Array.prototype.map.call(yxml.dom.childNodes, child => child.__yxml)
                                    .filter(id => id !== undefined)
  // 1. Check if any of the nodes was deleted
  for (let i = yxml._content.length - 1; i >= 0; i--) {
    let childType = yxml.get(i)
    if (!undeletedKnownChildren.some(undel => undel === childType)) {
      yxml.delete(i, 1)
    }
  }
  // 2. iterate
  let childNodes = yxml.dom.childNodes
  let len = childNodes.length
  for (let domCnt = 0, yCnt = 0; domCnt < len; domCnt++) {
    let child = childNodes[domCnt]
    if (child.__yxml != null) {
      if (child.__yxml === false) {
        continue
      }
      if (yCnt < yxml.length) {
        let expectedNode = yxml.get(yCnt)
        if (expectedNode !== child.__yxml) {
          // 2.3 Not expected node
          let index = yxml._content.findIndex(c => c.type[0] === child.__yxml._model[0] && c.type[1] === child.__yxml._model[1])
          if (index < 0) {
            // element is going to be deleted by its previous parent
            child.__yxml = null
          } else {
            yxml.delete(index, 1)
          }
          yCnt += yxml.insertDomElements(yCnt, [child])
        } else {
          yCnt++
        }
        // if this is the expected node id, just continue
      } else {
        // 2.2 fill _conten with child nodes
        yCnt += yxml.insertDomElements(yCnt, [child])
      }
    } else {
      // 2.1 A new node was found
      yCnt += yxml.insertDomElements(yCnt, [child])
    }
  }
}

@@ -2115,36 +2115,107 @@
 %7B%0A  
-let undeletedKnownChildren =
+// list of known children. anything else should be deleted%0A  let knownChildren =%0A    new Set(%0A     
  Arr
@@ -2284,38 +2284,8 @@
 ml)%0A
-                              
     
@@ -2318,16 +2318,55 @@
 efined)%0A
+    )%0A  let deleteChildren = new Set()%0A
   // 1. 
@@ -2504,18 +2504,9 @@
 f (!
-undeletedK
+k
 nown
@@ -2518,32 +2518,12 @@
 ren.
-some(undel =%3E undel === 
+has(
 chil
@@ -2542,24 +2542,36 @@
     
-yxml.
 delete
-(i, 1
+Children.add(childType
 )%0A  
@@ -2821,19 +2821,110 @@
 == false
-) %7B
+ %7C%7C deleteChildren.has(child.__yxml)) %7B%0A        // should be ignored or is going to be deleted
 %0A       
@@ -3744,16 +3744,16 @@
 s found%0A
-
       yC
@@ -3798,18 +3798,422 @@
 ild%5D)%0A    %7D%0A  %7D%0A
+  // 3. actually delete deleteChildren%0A  // We should not delete children before inserting because there%0A  // are some weird scrolling issues: E.g. format first line bold.%0A  // The formatted text will be out of viewport for the remote user.%0A  for (let i = yxml._content.length - 1; i %3E= 0; i--) %7B%0A    let childType = yxml.get(i)%0A    if (deleteChildren.has(childType)) %7B%0A      yxml.delete(i, 1)%0A    %7D%0A  %7D%0A
 %7D%0A

fix weird scrolling issue: text is out of view when first line is formatted bold