module.exports = render

var diff = require('./')
var get = require('keyarray-get')
var splitStrings = require('./split-strings')
var splitWords=  require('./split-words')
var treeify = require('./treeify-patch')

function render(a, b) {
  var editTree = treeify(diff(a, b, splitStrings))
  return renderForm(a, editTree) }

function renderForm(form, editTree) {
  var original = form.content.reduce(
    function(returned, element, index) {
      if (typeof element === 'string') {
        returned.push(renderText(element))
        return returned }
      else if (element.hasOwnProperty('form')) {
        return returned.concat(
          renderForm(
            element.form,
            get(editTree, [ 'content', index, 'form' ], [ ]))) }
      else {
        return returned.concat(element) } },
    [ ])
  var editsHere = get(editTree, [ 'content', 'edits' ], [ ])
  return editsHere
    .reduce(
      function(returned, element) {
        var op = element.op
        var path = element.path
        var contentElementIndex = getNth(returned, path[0], true)
        var contentElement = returned[contentElementIndex]
        var splitIndex
        if (op === 'remove') {
          if (path.length === 2) {
            getNth(contentElement.splits, path[1]).del = true }
          else {
            contentElement.del = true } }
        else if (op === 'add') {
          if (path.length === 2) {
            splitIndex = getNth(contentElement.splits, path[1], true)
            contentElement.splits.splice(
              splitIndex, 0,
              { text: element.value, ins: true }) }
          else {
            if (element.value.hasOwnProperty('splits')) {
              var rendered = renderSplits(element.value.splits)
              rendered.ins = true
              returned.splice(contentElementIndex, 0, rendered) }
            else {
              element.value.ins = true
              returned.splice(contentElementIndex, 0, element.value) } } }
        else if (op === 'replace') {
          if (path.length === 2) {
            splitIndex = getNth(contentElement.splits, path[1], true)
            var split = contentElement.splits[splitIndex]
            split.del = true
            contentElement.splits.splice(
              splitIndex, 0, { text: element.value, ins: true }) }
          else {
            element.value.ins = true
            contentElement.del = true
            returned.splice(contentElementIndex, 0, element.value) } }
        return original },
      original) }

function renderText(text) {
  return renderSplits(splitWords(text)) }

function renderSplits(splits) {
  return {
    splits: splits.map(function(split) {
      return { text: split } }) } }

function getNth(elements, target, returnIndex) {
  var length = elements.length
  var count = 0
  for (var index = 0; index < length; index++) {
    var element = elements[index]
    if (!element.hasOwnProperty('del')) {
      if (count === target) {
        return ( returnIndex ? index : element ) }
      count++ } }
  return ( index + 1 ) }

@@ -924,23 +924,25 @@
 turned, 
-element
+operation
 ) %7B%0A    
@@ -954,23 +954,25 @@
 ar op = 
-element
+operation
 .op%0A    
@@ -986,23 +986,25 @@
  path = 
-element
+operation
 .path%0A  
@@ -1561,39 +1561,41 @@
         %7B text: 
-element
+operation
 .value, ins: tru
@@ -1634,23 +1634,25 @@
     if (
-element
+operation
 .value.h
@@ -1720,23 +1720,25 @@
 rSplits(
-element
+operation
 .value.s
@@ -1869,39 +1869,41 @@
 %7B%0A              
-element
+operation
 .value.ins = tru
@@ -1950,39 +1950,41 @@
 lementIndex, 0, 
-element
+operation
 .value) %7D %7D %7D%0A  
@@ -2289,23 +2289,25 @@
 %7B text: 
-element
+operation
 .value, 
@@ -2350,23 +2350,25 @@
         
-element
+operation
 .value.i
@@ -2467,23 +2467,25 @@
 dex, 0, 
-element
+operation
 .value) 

Use "operation" variable name for patch operations