<body style="background: auto; margin: 0px; padding: 0px">
  <textarea
    id="texty"
    style="width: 100%; height: 100%; box-sizing: border-box"
  ></textarea>
</body>
<script src="https://braid.org/code/myers-diff1.js"></script>
<script src="https://unpkg.com/braid-http@~1.3/braid-http-client.js"></script>
<script src="/simpleton-client.js"></script>
<script>
  let simpleton = simpleton_client(location.pathname, {
    apply_remote_update: ({ state, patches }) => {
      if (state !== undefined) texty.value = state;
      else apply_patches_and_update_selection(texty, patches);
      return texty.value;
    },
    generate_local_diff_update: (prev_state) => {
      var patches = diff(prev_state, texty.value);
      if (patches.length === 0) return null;
      return { patches, new_state: texty.value };
    },
    on_error: (e) => {
      texty.disabled = true
      texty.style.background = '#fee'
      texty.style.border = '4px solid red'
    }
  });

  texty.value = "";
  texty.oninput = (e) => simpleton.changed();

  function diff(before, after) {
    let diff = diff_main(before, after);
    let patches = [];
    let offset = 0;
    for (let d of diff) {
      let p = null;
      if (d[0] == 1) p = { range: [offset, offset], content: d[1] };
      else if (d[0] == -1) {
        p = { range: [offset, offset + d[1].length], content: "" };
        offset += d[1].length;
      } else offset += d[1].length;
      if (p) {
        p.unit = "text";
        patches.push(p);
      }
    }
    return patches;
  }

  function apply_patches_and_update_selection(textarea, patches) {
    let offset = 0;
    for (let p of patches) {
      p.range[0] += offset;
      p.range[1] += offset;
      offset -= p.range[1] - p.range[0];
      offset += p.content.length;
    }

    let original = textarea.value;
    let sel = [textarea.selectionStart, textarea.selectionEnd];

    for (var p of patches) {
      let range = p.range;

      for (let i = 0; i < sel.length; i++)
        if (sel[i] > range[0])
          if (sel[i] > range[1]) sel[i] -= range[1] - range[0];
          else sel[i] = range[0];

      for (let i = 0; i < sel.length; i++)
        if (sel[i] > range[0]) sel[i] += p.content.length;

      original =
        original.substring(0, range[0]) +
        p.content +
        original.substring(range[1]);
    }

    textarea.value = original;
    textarea.selectionStart = sel[0];
    textarea.selectionEnd = sel[1];
  }
</script>