document.addEventListener("DOMContentLoaded", async () => { "use strict";
const secure = location.protocol === "https:";
const $ = (s,c) => (c||document).querySelector(s);
function $$(x,y,z,a){a=(z||document).querySelectorAll(x);if(typeof y=="function")[].forEach.call(a,y);return a}
function m(a,b,c){c=document;b=c.createElement(b||"p");b.innerHTML=a.trim();for(a=c.createDocumentFragment();c=b.firstChild;)a.appendChild(c);return a.firstChild}
function debounce(fn, delay) {
  let timeout = null;
  return (...args) => {
    if (timeout) clearTimeout(timeout);
    timeout = setTimeout(() => {
      timeout = null;
      fn.apply(null, args);
    }, delay||500);
  }
}
//sock.init(`ws${secure?"s":""}://${location.host}/ws`);
//sock.on("hello", e => {
//  console.log("hello", e);
//  sock.send("world", {foo:"bar"});
//});
//if ("serviceWorker" in navigator) {
//  navigator.serviceWorker.register("sw.js")
//    .then(() => console.log("Service worker registered"));
//}
function drawNote(note) {
  const el = m(`
`);
  const ta = $("textarea", el)
  ta.addEventListener("input",
    debounce(() => { saveNote(note.id, ta.value); }, 500));
  function resizeTextarea() { // TODO simplify
    el.style.height = (el.scrollHeight) + "px";
    ta.style.height = ""; ta.style.height = (ta.scrollHeight) + "px";
    el.style.height = "";
  }
  ta.addEventListener("input", resizeTextarea);
  ta.addEventListener("focus", resizeTextarea);
  window.addEventListener("resize", resizeTextarea);
  setTimeout(resizeTextarea);
  $("#notes").appendChild(el);
}
async function getNote(id) {
  const res = await fetch(`${id}`);
  const note = await res.json();
  console.log(note);
  drawNote(note);
}
async function getList() {
  const res = await fetch("/list");
  const list = await res.json();
  console.log(list);
  return Promise.all(list.map(id => getNote(id)));
}
async function saveNote(id, content) {
  const res = await fetch("/"+id, {
    method: "POST",
    body: JSON.stringify({id, content}),
  });
  const note = await res.json();
  console.log(note);
}
async function newNote() {
  const res = await fetch("/new", {
    method: "POST",
  });
  const note = await res.json();
  console.log(note);
  drawNote(note);
}
$("#add-btn").addEventListener("click", newNote);
async function getUserData() {
  const res = await fetch(`/user`);
  const user = await res.json();
  console.log(user);
}
async function getUserSessions() {
  const res = await fetch(`/session-list`);
  const sessions = await res.json();
  console.log(sessions);
}
function showSignIn() {
  const hash = location.hash.slice(2).replace(/^sign-in(\/to\/)?/,"");
  history.replaceState("sign-in","","#/sign-in"+(hash?"/to/"+hash:""));
  $("#sign-in-dialog").showModal();
}
$("#sign-in-dialog").addEventListener("cancel", e => e.preventDefault());
$("#sign-in-username").addEventListener("input", e => e.target.classList.remove("error"));
$("#sign-in-password").addEventListener("input", e => e.target.classList.remove("error"));
$("#sign-in-basic-go").addEventListener("click", async e => {
  e.preventDefault();
  $("#sign-in-error").textContent = "";
  const inputs = [
    $("#sign-in-username"),
    $("#sign-in-password"),
    $("#sign-in-keep-session"),
    $("#sign-in-basic-go"),
  ];
  const validatedInputs = inputs.slice(0,2);
  if (validatedInputs.map(e => {
    if (!e.checkValidity()) {
      e.classList.add("error");
      return true; }
  }).reduce((a,e) => a||e, false)) return;
  inputs.forEach(e => e.disabled = true);
  $("#sign-in-form").classList.add("loading");
  const res = await fetch("/login", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
      username: $("#sign-in-username").value,
      password: $("#sign-in-password").value,
      keepSession: $("#sign-in-keep-session").checked,
    })
  });
  inputs.forEach(e => e.disabled = false);
  $("#sign-in-form").classList.remove("loading");
  if (!res.ok) {
    $("#sign-in-error").textContent = res.status+" "+res.statusText;
    return;
  }
  const json = await res.json();
  console.log(json);
  if (!json.success) {
    $("#sign-in-error").textContent = json.msg;
    return;
  }
  if (json.mustChangePassword) {
    alert("Must change password (TODO)");
    // TODO
    return;
  }
  const hash = location.hash.slice(9);
  history.replaceState("","","#/"+hash);
  // TODO load location
  getUserData();
  getList();
  $("#sign-in-dialog").close();
});
$("#change-password").addEventListener("click", async () => {
  const res = await fetch("/change-password", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
      username: $("#username").value, // TODO
      password: $("#password").value, // TODO
      newPassword: $("#new-password").value,
      keepSession: $("#keep-session").checked,
    })
  });
  const json = await res.json();
  console.log(json);
  getUserData();
});
$("#change-username").addEventListener("click", async () => {
  const res = await fetch("/change-username", {
    method: "POST",
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify({
      newUsername: $("#new-username").value,
      password: $("#password").value, // TODO
    })
  });
  const json = await res.json();
  console.log(json);
  getUserData();
});
$("#log-out").addEventListener("click", async () => {
  const res = await fetch("/logout", {
    method: "POST",
  });
  //const json = await res.json();
  //console.log(json);
  console.log("Logged out");
  $("#sign-in-dialog").showModal();
});
$("#log-out-everywhere").addEventListener("click", async () => {
  const res = await fetch("/deauth-all", {
    method: "POST",
  });
  console.log("Logged out everywhere");
  showSignIn();
});
try { await getUserData(); await getList(); await getUserSessions(); } catch(e) { showSignIn(); }
(() => {
  let prevScroll = 0;
  window.addEventListener("scroll", () => {
    document.querySelector("#toolbar").classList[
      (window.scrollY && window.scrollY > prevScroll)?"add":"remove"]("hide");
    prevScroll = window.scrollY;
  });
})();
// TODO make sure to save unsynced delta even if token has expired, then sync when logged in
// TODO Cookie consent on signup; "only necessary for maintaining user session and cached data"
// TODO "Review sessions" popup client-side when relogin required on a token which shouldn't have expired yet
// TODO prevent data: and javascript: links?
//      Also embedding of external content?
//      encodeURI *AND* encode for attribute (quote marks etc)
//      https://github.com/cure53/DOMPurify
//
//      elem.textContent = dangerVariable; !!!!!!!!!
//      elem.insertAdjacentText(dangerVariable);
//      elem.className = dangerVariable;
//      elem.setAttribute(safeName, dangerVariable);
//      formfield.value = dangerVariable;
//      document.createTextNode(dangerVariable);
//      document.createElement(dangerVariable);
//      elem.innerHTML = DOMPurify.sanitize(dangerVar);
//      https://github.com/cure53/DOMPurify/blob/main/src/attrs.js
//      https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html
// TODO note kebab menu could be a