const urlHost = window.location.href.substr(0, window.location.href.lastIndexOf("/"));

// the following object keeps the file extension for the select option values of 'from' and 'to'
// access: value = extension["key"]
const extension = {"asciidoc_legacy": "asciidoc", "asciidoc": "asciidoc", "beamer": "tex", "biblatex": "bib", "bibtex": "bibtex", "chunkedhtml": "zip", "commonmark_x": "md", "commonmark": "md", "context": "tex", "creole": "txt", "csljson": "json", "csv": "csv", "docbook5": "xml", "docbook": "xml", "docx": "docx", "dokuwiki": "txt", "dzslides": "html", "endnotexml": "xml", "epub2": "epub", "epub3": "epub", "epub": "epub", "fb2": "fb2", "gfm": "md", "haddock": "md", "html4": "html", "html5": "html", "html": "html", "icml": "icml", "ipynb": "ipynb", "jats_archiving": "xml", "jats_articleauthoring": "xml", "jats_publishing": "xml", "jats": "xml", "jira": "txt", "json": "json", "latex": "tex", "man": "man", "markdown_mmd": "md", "markdown_phpextra": "md", "markdown_strict": "md", "markdown": "md", "markua": "md", "mediawiki": "txt", "ms": "ms", "muse": "txt", "native": "hs", "odt": "odt", "opendocument": "odf", "opml": "xml", "org": "txt", "pdf": "pdf", "plain": "txt", "pptx": "pptx", "preview": "html", "revealjs": "html", "ris": "ris", "rst": "rst", "rtf": "rtf", "s5": "html", "slideous": "html", "slidy": "html", "t2t": "t2t", "tei": "tei", "texinfo": "texi", "textile": "textile", "tikiwiki": "txt", "tsv": "tsv", "twiki": "txt", "typst": "typ", "vimwiki": "txt", "xwiki": "txt", "zimwiki": "txt"};

function pandoc(alert) {
  var url = urlHost + '/pandoc.php';
  if (typeof alert === 'undefined') {
    alert === false;
  }
  // checkboxes
  var standalone  = document.getElementById('standalone').checked;
  var tableOfContents  = document.getElementById('table-of-contents').checked;
  var numberSections  = document.getElementById('number-sections').checked;
  var citeproc  = document.getElementById('citeproc').checked;
  // selects
  var wrap  = document.getElementById('wrap').value;
  var highlightStyle  = document.getElementById('highlight-style').value;
  var htmlMathMethod  = document.getElementById('html-math-method').value;
  // files
  var useInputFile  = document.getElementById('cb-inputfile').checked;
  var inputFileExtension = extension[document.getElementById('from').value];
  // docx, epub or odt must be dilivered as a file
  if (!useInputFile && (inputFileExtension == 'docx' || inputFileExtension == 'epub' || inputFileExtension == 'odt')) {
    if (alert === true) {
      document.getElementById('options').setAttribute("open", "open");
      document.getElementById('cb-inputfile').checked = true;
      checkInputFile();
      pushDialog("Error: For conversion from '" + inputFileExtension + "' you must select a file as input.", "error", "inputfile");
    }
    return;
  }
  var inputFile = false;
  if (useInputFile) {
    inputFile = document.getElementById('inputfile').files[0];
  }
  if (!inputFile && useInputFile) {
    if (alert === true) {
      pushDialog("Error: Nothing to convert.\nYou must select a file as input.", "error", "inputfile");
    }
    return;
  }
  var useOutputFile  = document.getElementById('cb-outputfile').checked;
  var outputFileExtension = extension[document.getElementById('to').value];
  // content
  var from  = document.getElementById('from').value;
  if (from === "none") {
    if (alert === true) {
      pushDialog("Error: You must select an input format in the 'From' pulldown menu.", "error", "from");
    }
    return;
  }
  var to  = document.getElementById('to').value;
  var input  = document.getElementById('input').value;
  if (isEmpty(input) && !useInputFile) {
    if (alert === true) {
      pushDialog("Error: Nothing to convert.\n\nYou must either write something into the 'Input field' or select a file as input in the 'Options'.", "error");
    }
    return;
  }
  var formData = new FormData();
  // checkboxes
  formData.set('standalone', standalone);
  formData.set('tableOfContents', tableOfContents);
  formData.set('numberSections', numberSections);
  formData.set('citeproc', citeproc);
  // selects
  formData.set('wrap', wrap);
  formData.set('highlightStyle', highlightStyle);
  formData.set('htmlMathMethod', htmlMathMethod);
  // files
  formData.set('useInputFile', useInputFile);
  formData.set('inputFileExtension', inputFileExtension);
  formData.set('inputFile', inputFile);
  formData.set('useOutputFile', useOutputFile);
  formData.set('outputFileExtension', outputFileExtension);
  // content
  formData.set('from', from);
  formData.set('to', to);
  formData.set('input', input);

  pushDialog('Converting with pandoc', 'busy');

  fetch(url, {
      method: 'POST',
      body: formData
    })
    .then(response => {
      if (!response.ok) {
          throw new Error("HTTP error " + response.status);
      }
      if (useOutputFile) {
        return response.blob();
      } else {
        return response.text();
      }
    })
    .then(content => {
      if (useOutputFile) {
        // output as file
        let blob = new Blob([content], {type: 'text/plain'});
        let download = document.getElementById('download');
        download.href = URL.createObjectURL(blob);
        let timestamp = new Date().toISOString().replaceAll('T','_').replaceAll(':', '-').slice(0, 19);
        download.setAttribute("download", "output_" + timestamp + "." + outputFileExtension);
        document.getElementById("download").innerText = "Download output_" + timestamp + "." + outputFileExtension;
        // close the busy dialog
        dialog.close()
      } else {
        if (to === "preview") {
          document.getElementById("output").innerHTML = content;
        } else {
          // delete all elements contents
          document.getElementById("output").innerHTML = "";
          var node = document.createElement("pre");
          document.getElementById("output").appendChild(node);
          node.innerText = content;
        }
        // close the busy dialog
        dialog.close()
      }
    })
    .catch(error => {
      // close the busy dialog
      dialog.close()
      pushDialog('Error fetching pandoc output: ' + error, 'error')
      console.log('Error fetching pandoc output: ' + error);
    });
}

// option toc needs option standalone so check standalone
function toggleStandalone() {
  if (document.getElementById('table-of-contents').checked === true) {
    document.getElementById('standalone').checked = true;
  }
}

// option toc needs option standalone so uncheck toc if unchecking standalone
function toggleToc() {
  if (document.getElementById('standalone').checked === false) {
    document.getElementById('table-of-contents').checked = false;
  }
}

function checkInputFile() {
  if (document.getElementById('cb-inputfile').checked === true) {
    document.getElementById('inputfile').removeAttribute("disabled");
    document.getElementById('input').setAttribute("disabled", "disabled");
    document.getElementById('label-inputfield').classList.add("disabled");
  } else {
    document.getElementById('inputfile').setAttribute("disabled", "disabled");
    document.getElementById('input').removeAttribute("disabled");
    document.getElementById('label-inputfield').classList.remove("disabled");
  }
}

function checkOutputFile() {
  if (document.getElementById('cb-outputfile').checked === true) {
    document.getElementById('download').setAttribute("href", "#");
    document.getElementById('copy').setAttribute("disabled", "disabled");
    document.getElementById('output').classList.add("disabled");
    document.getElementById('output').innerText = "";
    document.getElementById('label-outputfield').classList.add("disabled");
  } else {
    document.getElementById('download').removeAttribute("href");
    document.getElementById("download").innerText = "";
    document.getElementById('copy').removeAttribute("disabled");
    document.getElementById('output').classList.remove("disabled");
    document.getElementById('label-outputfield').classList.remove("disabled");
  }
}

// This will return the raw HTML, but perhaps you want to do something different,
// for example: recursively embed computed styles:
// https://developer.mozilla.org/en-US/docs/Web/API/Window/getComputedStyle
function serializeElement(element) {
  return element.outerHTML;
}

async function copyOutput() {
  var element = document.getElementById('output');
  const html = serializeElement(element);
  const htmlBlob = new Blob([html], { type: 'text/html' });
  const text = element.textContent ?? '';
  const textBlob = new Blob([text], { type: 'text/plain' });
  const clipboardItem = new ClipboardItem({
      [htmlBlob.type]: htmlBlob,
      [textBlob.type]: textBlob,
  });
  return navigator.clipboard.write([clipboardItem]);
}

// adapt height of textarea responding to the contents
// it's only working with the corresponding css
function adaptTextareaSize() {
  const growers = document.querySelectorAll(".grow-wrap");
  growers.forEach((grower) => {
    const textarea = grower.querySelector("textarea");
    textarea.addEventListener("input", () => {
      grower.dataset.replicatedValue = textarea.value;
    });
  });
}

function pushDialog(text, type, elementById) {
  var dialogText = document.getElementById('dialogText');
  dialogText.innerText = text;
  if (type === "error") {
    document.getElementById('dialog').classList.add('error-dialog');
    document.getElementById('dialog').classList.remove('busy-dialog');
    dialogText.role = 'alert';
    if (typeof elementById !== 'undefined') {
      document.getElementById(elementById).focus();
    }
  } else if (type === "busy") {
    document.getElementById('dialog').classList.remove('error-dialog');
    document.getElementById('dialog').classList.add('busy-dialog');
  }
  dialog.showModal();
}

// test if a string only contains whitespaces and newlines
function isEmpty(string) {
  return (string.length === 0 || !string.trim());
};

function useExample() {
  var inputField = document.getElementById("input");
  inputField.value = example;
  document.getElementById('from').value = 'markdown';
  document.getElementById('cb-inputfile').checked = false;
  checkInputFile();
  // fire onInput event to adapt height of textarea
  var eventInput = new Event('input', { bubbles: true });
  inputField.dispatchEvent(eventInput);
  // execute pandoc to show example on preview
  pandoc();
}