{% for field_name, field_errors in form.errors.items() %}
{% for error in field_errors %}
<div class="flash-notice-narrow">{{ error }}</div>
{% endfor %}
{% endfor %}

<div id="term-form-container">
  <form id="term-form" name="term_form" method="POST">
    {{ form.hidden_tag() }}
    <div id="term">
      <div id="languageSel"
        {% if term.language_id is none and term.language is none %}
        {# show the language select box. #}
        {% else %}
        style="display:none;"
        {% endif %}>
        {{ form.language_id(class="form-control") }}
      </div>
  
      {{ form.original_text }}

      <div id="def-container">
        {{ form.text(class="form-control", value=(form.original_text.data or '')) }}
        <div class="term-element-box">
          <img src="{{ url_for('static', filename='icn/external.png') }}" title="Lookup" onclick="do_term_lookup()" />
          <img src="{{ url_for('static', filename='icn/eye.png') }}" title="Images" onclick="do_image_lookup()" />
        </div>
      </div>

      <div>{{ form.parentslist(class="form-control") }}</div>
  
      <div {% if hide_pronunciation %}style="display:none;"{% endif %}>
        {{ form.romanization(class="form-control") }}
      </div>

      <div id="translation-container">
        <div>{{ form.translation }}</div>
        <img {% if term.current_image %}style="grid-column: -1; display: block"{% endif %} 
        class="zoomableTermImage" 
        id="term_image" 
        src="{{ form.current_image.object_data or '' }}"/>
      </div>

      <div>{{ form.status(class="form-control") }}</div>

      <div>{{ form.current_image(class="form-control") }}</div>

      <div>{{ form.termtagslist(class="form-control") }}</div>

      <div id="term-button-container">
        <a href="" onclick="show_term_sentences(); return false;">Sentences</a>
        <div class="term-element-box">
          {% if term.id %}
          <button id="delete" type="button" class="btn" onclick="deleteTerm()">Delete</button>
          {% endif %}
          <button id="submit" type="submit" class="btn btn-primary">Save</button>
        </div>
      </div>
    </div>
  </form>
</div>


<script type="text/javascript">

  // TODO zzfuture fix: acceptance tests for all interactions

  // Monitor state of form change.
  let form_changed = false;

  $("form :input").change(function() {
      form_changed = true;
  });

  let setup_parent_tagify = function(input) {
    const tagify = new Tagify(input, {
      placeholder: 'Parents',
      editTags: false,
      autoComplete: { enabled: true, rightKey: true, tabKey: true },
      enforceWhitelist: false,
      whitelist: [],
      dropdown: {
        enabled: 2,  // Min 2 chars - this doesn't seem to work.
        maxItems: 15,
        mapValueTo: 'suggestion',  // Field to display
        placeAbove: false,  // Always put the dropdown below the textbox
      },
    });  // end tagify

    tagify.on('click', function (e) {
      // Exit early if language not set - will not handle, too complicated.
      const langid = document.getElementById("language_id").value;
      const clickedTagText = e.detail.data.value;
      if (langid === "0" || clickedTagText === '') {
        return;
      }

      if (form_changed) {
        const msg = 'You have unsaved changes, going to the parent will lose them.  Continue?';
        if (!confirm(msg))
          return;
      }

      let url = '';
      if ("{{ embedded_in_reading_frame }}" == "True") {
        url = `/read/termform/${langid}/${clickedTagText}`;
      } else {
        url = `/term/editbytext/${langid}/${clickedTagText}`;
      }
      window.location.href = url;
    });

    // Autocomplete
    var controller;
    tagify.on('input', onInput);
    function onInput(e) {
      tagify.whitelist = null;  // Reset whitelist.
      if (e.detail.value == '' || e.detail.value.length < 2) {
        controller && controller.abort();
        tagify.whitelist = [];
        tagify.loading(false).dropdown.hide();
        return;
      }
      const s = encodeURIComponent(e.detail.value);
      // console.log(s);
      const langid = parseInt(document.getElementById('language_id').value);

      // https://developer.mozilla.org/en-US/docs/Web/API/AbortController/abort
      controller && controller.abort()
      controller = new AbortController()

      let make_dropdown = function(hsh) {
        // console.log(`text: ${hsh.text}`);
        const txt = decodeURIComponent(hsh.text);
        let t = hsh.translation ?? '';
        if (t == '') {
          return txt;
        }
        t = t.replaceAll("\n", "; ").replaceAll("\r", "");
        const maxlen = 70
        if (t.length > maxlen) {
          t = t.substring(0, maxlen) + "...";
        }
        return `${txt} (${t})`;
      };

      tagify.loading(true);  // spinning animation during fetch.
      fetch(`/term/search/${s}/${langid}`, {signal:controller.signal})
        .then(RES => RES.json())
        .then(function(data) {
          const newWhitelist = data.map((a) => ({
            "value": a.text,
            "suggestion": make_dropdown(a)
          }));
          tagify.whitelist = newWhitelist; // update whitelist Array in-place
          const sdecode = decodeURIComponent(s);
          tagify.loading(false).dropdown.show(sdecode); // render the suggestions dropdown
        }).catch(err => {
          if (err.name === 'AbortError') {
            // Do nothing, fetch was aborted due to another fetch.
            // console.log('AbortError: Fetch request aborted');
          }
          else {
            console.log(`error: ${err}`);
          }
        });
    };  // end function onInput

    return tagify;
  }


  var TAGS = {{ tags | safe }};

  let setup_term_tags_tagify = function(input) {
    const tagify = new Tagify(input, {
      placeholder: 'Tags',
      editTags: false,
      autoComplete: { enabled: true, rightKey: true, tabKey: true },
      enforceWhitelist: false,
      whitelist: TAGS
    });  // end tagify
  };

  // TODO zzfuture fix: check term autofocus
  // lute.js should send an "autofocus" flag, I believe.
  let handleAutofocus = function() {
    const wordfield = $('#text');
    const transfield = $('#translation');

    if ($('#autofocus').val() != 'false') {
      if (wordfield.val()) {
        transfield.focus();
      }
      else {
        wordfield.focus();
      }
    }
  };

  $(document).ready(function () {
    var parentslist = document.getElementById('parentslist');
    var parents_tagify = setup_parent_tagify(parentslist);
    var termtagslist = document.getElementById('termtagslist');
    var termtags_tagify = setup_term_tags_tagify(termtagslist);

    if (($('#text').val() ?? '') != '') {
      do_term_lookup(false);
    }

    // Post message re form opened.
    // Note have to use this rather than the better
    // this.dispatchEvent(new Event("termFormOpened"));
    // because this form is opened in a frame.
    window.parent.postMessage({ event: "LuteTermFormOpened" }, "*");
  });

  /** LOOKUPS */

  var LANGUAGES = {{ language_dicts | safe }};

  // Term lookups cycle through the available dictionaries in the language.
  var termdictindex = 0;

  let open_new_lookup_window = function(url) {
    window.open(
      url,
      'otherwin',
      //'width=800, height=400, scrollbars=yes, menubar=no, resizable=yes, status=no'
    );
  };

  let get_lookup_url = function(dicturl, term) {
    let ret = dicturl;

    // Terms are saved with zero-width space between each token;
    // remove that for dict searches!
    const zeroWidthSpace = '\u200b';
    const sqlZWS = '%E2%80%8B';
    const cleantext = term.
          replaceAll(zeroWidthSpace, '').
          replace(/\s+/g, ' ');
    const searchterm = encodeURIComponent(cleantext).
          replaceAll(sqlZWS, '');
    ret = ret.replace('###', searchterm);
    // console.log(ret);
    return ret;
  };


  /** Parents are in the tagify-managed #parentslist input box. */
  let get_parents = function() {
    const pdata = $('#parentslist').val();
    if ((pdata ?? '') == '') {
      return [];
    }
    const j = JSON.parse(pdata)
    const parents = j.map(e => e.value);
    return parents;
  };


  let do_image_lookup = function() {
    const langid = $('#language_id').val();
    const text = $('#text').val();

    if (langid == null || langid == '' || parseInt(langid) == 0 || text == null || text == '') {
      alert('Please select a language and enter the term.');
      return;
    }

    let use_text = text;

    // If there is a single parent, use that as the basis of the lookup.
    const parents = get_parents();
    if (parents.length == 1)
      use_text = parents[0];

    const raw_bing_url = 'https://www.bing.com/images/search?q=###&form=HDRSC2&first=1&tsc=ImageHoverTitle';
    const binghash = raw_bing_url.replace('https://www.bing.com/images/search?', '');
    const url = `/bing/search/${langid}/${encodeURIComponent(use_text)}/${encodeURIComponent(binghash)}`;
    top.frames.dictframe.location.href = url;
    return;
  }


  /**
   * Either open a new window, or show the result in the correct frame.
   */
  let show_lookup_page = function(dicturl, text, langid, allow_open_new_web_page = true) {

    const is_bing = (dicturl.indexOf('www.bing.com') != -1);
    if (is_bing) {
      let use_text = text;
      const binghash = dicturl.replace('https://www.bing.com/images/search?', '');
      const url = `/bing/search/${langid}/${encodeURIComponent(use_text)}/${encodeURIComponent(binghash)}`;
      top.frames.dictframe.location.href = url;
      return;
    }

    // TODO zzfuture fix: fix_language_dict_asterisk
    // The URL shouldn not be prepended with trash
    // (e.g. "*http://" means "open an external window", while
    // "http://" means "this can be opened in an iframe."
    // Instead, each dict should have an "is_external" property.
    const is_external = (dicturl.charAt(0) == '*');
    if (is_external) {
      if (!allow_open_new_web_page) {
        console.log('Declining to open external web page.');
        return;
      }
      dicturl = dicturl.slice(1);
      const url = get_lookup_url(dicturl, text);
      open_new_lookup_window(url);
      return;
    }

    // Fallback: open in frame.
    const url = get_lookup_url(dicturl, text);
    top.frames.dictframe.location.href = url;
  };


  function do_term_lookup(allow_open_new_web_page = true) {
    const langid = $('#language_id').val();
    if (langid == null || langid == '' || parseInt(langid) == 0) {
      alert('Please select a language.');
      return;
    }

    const termdicts = LANGUAGES[langid].term;
    const usedict = termdicts[termdictindex];
    show_lookup_page(usedict, $('#text').val(), langid, allow_open_new_web_page);

    termdictindex++;
    if (termdictindex >= termdicts.length)
      termdictindex = 0;
  }

  function show_term_sentences() {
    const langid = $('#language_id').val();
    const txt = $('#text').val();
    // %E2%80%8B is the zero-width string.  The term is reparsed
    // on the server, so this doesn't need to be sent.
    const t = encodeURIComponent(txt).replaceAll('%E2%80%8B', '');
    if (langid == '0' || t == '')
      return;
    const url = `/term/sentences/${langid}/${t}`;
    top.frames.dictframe.location.href = url;
  }

  function deleteTerm() {
    const msg = "Are you sure you want to delete this term?\n\n" +
          "This action cannot be undone, and if this term has children, they will be orphaned.";
    if (!confirm(msg))
      return;

    $.post("/term/delete/{{ term.id }}", function( data ) {
      if ("{{ embedded_in_reading_frame }}" == "True") {
        // If on reading page, reload page
        parent.location.reload();
      }
      else {
        // If on term page, go to term listing
        window.location.href = '/term/index';
      }
    });
  }

</script>
