var sortState = {
  sortBy: "sortAuthor",
  sortOrder: "asc",
};

var admin = false;

var books;

function checkAdminMode() {
  fetch("/api/mode")
    .then((response) => response.json())
    .then((resp) => (admin = resp.Admin))
    .then(() => {
      if (admin) {
        var element = document.getElementById("addBook");
        element.addEventListener("click", (e) => {
          e.preventDefault();
          renderAddBookView();
        });
        element.classList.remove("hidden");
      }
    });
}

function loadBookList() {
  fetch("/api/books")
    .then((response) => response.json())
    .then((list) => {
      // prepare response
      list.forEach(apiResponseParsing);
      books = list;
      document.getElementById("search").addEventListener("input", rerender);
      document.getElementById("childrens").addEventListener("change", rerender);
      rerender();
    });
}

function rerender() {
  var searchValue = document.getElementById("search").value;
  var childrens = document.getElementById("childrens").checked;
  renderTable(search(searchValue, childrens));
}

function init() {
  checkAdminMode();
  loadBookList();
}

function renderAddBookView() {
  document.getElementById("current").innerHTML = AddBookTemplate();
  document.getElementById("lookup").addEventListener("click", (e) => {
    e.preventDefault();
    if (document.getElementById("isbn-13").value.length === 13) {
      getPossibleBooks(document.getElementById("isbn-13").value);
    } else {
      console.log("no isbn");
    }
  });
  document.getElementById("save").addEventListener("click", (e) => {
    e.preventDefault();
    saveBook({
      title: document.getElementById("title").value,
      authors: document.getElementById("authors").value.split(";"),
      sortAuthor: document.getElementById("sortAuthor").value,
      "isbn-10": document.getElementById("isbn-10").value,
      "isbn-13": document.getElementById("isbn-13").value,
      publisher: document.getElementById("publisher").value,
      format: document.getElementById("format").value,
      genre: document.getElementById("genre").value,
      series: document.getElementById("series").value,
      volume: document.getElementById("volume").value,
      year: document.getElementById("year").value,
      coverURL: document.getElementById("coverURL").value,
    });
  });
}

function getPossibleBooks(isbn) {
  fetch("/api/query", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ "isbn-13": isbn }),
  })
    .then((response) => response.json())
    .then((json) => {
      Object.keys(json).forEach((key) => {
        var elem = document.getElementById(key);
        if (elem !== null) {
          elem.value = json[key];
        }
      });
    });
}

function saveBook(book) {
  fetch("/api/books", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(book),
  }).then(() => {
    clearAddBookForm();
    loadBookList();
  });
}

function renderTable(bookList, sortField) {
  if (sortField) {
    sortState.sortOrder =
      sortState.sortBy === sortField && sortState.sortOrder === "asc"
        ? "desc"
        : "asc";
    sortState.sortBy = sortField;
  }
  bookList.sort((one, two) =>
    (one[sortState.sortBy] + one["sortTitle"]).localeCompare(
      two[sortState.sortBy] + two["sortTitle"]
    )
  );
  if (sortState.sortOrder === "desc") {
    bookList.reverse();
  }
  bookList.forEach((e, i) => (e.rowNumber = i)); // re-key

  // rendering
  var bookElement = document.getElementById("books");
  bookElement.innerHTML = TableTemplate(bookList);

  document.getElementById("bookCount").innerHTML = `${bookList.length} books`;

  // add listeners for selecting book to view
  Array.from(bookElement.querySelectorAll("tbody tr"))
    .slice(1) // remove header from Array
    .forEach((row) => {
      row.addEventListener("click", (e) => {
        // add listener to swap current book
        document.getElementById("current").innerHTML = BookTemplate(
          bookList[e.currentTarget.id]
        );
      });
    });
  // add sorting callbacks
  Array.from(bookElement.querySelectorAll("tbody tr th[data-sort-by]")).forEach(
    (row) => {
      row.addEventListener("click", function (e) {
        // only add callback when there's a sortBy attribute
        renderTable(bookList, e.target.dataset.sortBy);
      });
    }
  );
  // mark currently active column
  bookElement
    .querySelector("tbody tr th[data-sort-by=" + sortState.sortBy + "]")
    .classList.add(sortState.sortOrder);
}

function apiResponseParsing(book) {
  book.sortTitle = titleCleaner(book.title);
  if (!book["isbn-10"] && book["isbn-13"]) {
    book["isbn-10"] = ISBNfromEAN(book["isbn-13"]);
  }
  if (!book.coverURL && book["isbn-10"]) {
    book.coverURL =
      `https://images-na.ssl-images-amazon.com/images/P/` +
      book["isbn-10"] +
      `.01.LZZ.jpg`;
  }
  return book;
}

function search(searchBy, includeChildrensBooks) {
  searchBy = searchCleaner(searchBy);
  return books.filter(
    ({ title, authors, genre, publisher, series, year, childrens }) => {
      var inSearch = true;
      if (searchBy !== "") {
        inSearch = Object.values({
          title,
          authors: authors.join(" "),
          genre,
          publisher,
          series,
          year,
        }).find((field) => searchCleaner(field).indexOf(searchBy) !== -1);
      }
      if (!includeChildrensBooks) {
        return inSearch && !childrens;
      }
      return inSearch;
    }
  );
}

function titleCleaner(title) {
  return title
    .replace('"', "")
    .replace(":", "")
    .replace(/^(An?|The)\s/i, "");
}

function searchCleaner(str) {
  return str
    .toLowerCase()
    .replaceAll('"', "")
    .replaceAll(":", "")
    .replaceAll("'", "")
    .replaceAll(" ", "");
}

function ISBNfromEAN(EAN) {
  ISBN = EAN.slice(3, 12);
  var checkdigit =
    (11 - (ISBN.split("").reduce((s, n, k) => s + n * (10 - k), 0) % 11)) % 11;
  return ISBN + (checkdigit === 10 ? "X" : checkdigit);
}

function clearAddBookForm() {
  document
    .getElementById("newBookForm")
    .childNodes.forEach((node) =>
      node.nodeName === "LABEL" ? (node.lastChild.value = "") : null
    );
}

function BookTemplate({
  "isbn-13": isbn13,
  "isbn-10": isbn10,
  authors,
  coverURL,
  format,
  publisher,
  series,
  signed,
  title,
  volume,
  year,
}) {
  return `<img ${coverURL ? `src="${coverURL}"` : ``}/>
  <div class="bookDetails">
    <h1>${title}</h1>
    <h2>${authors}</h2>
    <span>${[isbn10, isbn13].filter((v) => v != "").join(" / ")}</span><br/>
    <span>${publisher}, ${year}</span><br/>
    ${
      series
        ? `<span>${series}${volume ? `, Volume ${volume}` : ""}</span><br/>`
        : ""
    }
    ${signed ? "<span>Signed by the author ✒</span><br/>" : ""}
    <span>${format}</span>
    ${admin ? `<a href="#">Edit Book</a>` : ""}
  </div>`;
}

function TableRowTemplate({
  "isbn-13": isbn13,
  "isbn-10": isbn10,
  authors,
  publisher,
  rowNumber,
  signed,
  title,
  year,
}) {
  return `<tr class="tRow" id="${rowNumber}">
    <td class="title">
      ${title} ${
    signed ? '<span class="signed" title="Signed by the author" >✒</span>' : ""
  }
    </td>
    <td class="author">${authors}</td>
    <td class="publisher">${publisher}</td>
    <td class="year">${year}</td>
    <td class="isbn">${isbn13 ? isbn13 : isbn10}</td>
  </tr>`;
}

function TableTemplate(books) {
  return `<table class="bookTable">
    <tr>
      <th data-sort-by="sortTitle" class="tHeader title">Title</th>
      <th data-sort-by="sortAuthor" class="tHeader author">Author</th>
      <th data-sort-by="publisher" class="tHeader publisher">Publisher</th>
      <th data-sort-by="year" class="tHeader year">Year</th>
      <th class="tHeader isbn">ISBN</th>
    </tr>${books.reduce((acc, book) => {
      return acc.concat(TableRowTemplate(book));
    }, "")} </table>`;
}

function AddBookTemplate() {
  return `<div class="addBookView">
    <div id="newBookForm">
      ${[
        { name: "Title", id: "title", type: "text" },
        { name: "Authors", id: "authors", type: "text" },
        { name: "SortAuthor", id: "sortAuthor", type: "text" },
        { name: "ISBN10", id: "isbn-10", type: "text" },
        { name: "ISBN13", id: "isbn-13", type: "text" },
        { name: "Publisher", id: "publisher", type: "text" },
        { name: "Format", id: "format", type: "text" },
        { name: "Genre", id: "genre", type: "text" },
        { name: "Series", id: "series", type: "text" },
        { name: "Volume", id: "volume", type: "text" },
        { name: "Year", id: "year", type: "text" },
        { name: "CoverURL", id: "coverURL", type: "text" },
        { name: "Signed", id: "signed", type: "checkbox" },
        { name: "Childrens", id: "childrens", type: "checkbox" },
      ].reduce((acc, field) => {
        return acc.concat(
          `<label>${field.name} <input
              type="${field.type}"
              name="${field.name.toLowerCase()}"
              id="${field.id}"
            /></label><br/>`
        );
      }, "")}
      <input id="lookup" type="submit" value="look up">
      <input id="save" type="submit" value="save">
    </div>
  </div>`;
}
