/**
 * Retrieve data from an API.
 * @param {String} api - The API url.
 * @returns {Promise} The result from api fetching.
 */
async function fetchData(api) {
  const headers = new Headers();
  const init = {
    method: "GET",
    headers,
    mode: "cors",
    cache: "default",
  };
  const response = await fetch(api, init);
  const result = await response.json();
  return result;
}
/**
 * Create a list item with a link.
 * @param {Object} data - An object containing an id and an username.
 * @returns {HTMLElement} A list item containing a link.
 */
function getListItem(data) {
  const item = document.createElement("li");
  const link = document.createElement("a");
  link.textContent = data.username;
  link.href = `?user=${data.id}`;
  link.id = `user-${data.id}`;
  link.classList.add("users-list__link");
  item.appendChild(link);
  item.classList.add("users-list__item");
  return item;
}
/**
 * Print the users list.
 * @param {Object[]} users - An array of user object.
 */
function printUsersList(users) {
  const list = document.querySelector(".users-list");
  users.map((user) => list.appendChild(getListItem(user)));
}
/**
 * Create a description term element.
 * @param {String} body - The description term body.
 * @returns {HTMLElement} The description term element.
 */
function createUserInfoDt(body) {
  const dt = document.createElement("dt");
  dt.classList.add("user-info__label");
  dt.textContent = body;
  return dt;
}
/**
 * Create a description details element.
 * @param {String} body - The description details body.
 * @param {Boolean} [hasHTML] - True if body contains HTML; false otherwise.
 * @returns {HTMLElement} The description details element.
 */
function createUserInfoDd(body, hasHTML = false) {
  const dd = document.createElement("dd");
  dd.classList.add("user-info__content");
  hasHTML ? (dd.innerHTML = body) : (dd.textContent = body);
  return dd;
}
/**
 * Get the markup to display info for a given user.
 * @param {Object} user - An user with fullname, email address, phone & website.
 * @returns {Object} Two HTMLElement: title and body.
 */
function getUserInfoTemplate(user) {
  const userAddress = `${user.address.suite}
${user.address.street}
${user.address.zipcode} ${user.address.city}`;
  const fullName = document.createElement("h2");
  const userDetails = document.createElement("dl");
  const emailLabel = createUserInfoDt("Email");
  const email = createUserInfoDd(user.email);
  const addressLabel = createUserInfoDt("Address");
  const address = createUserInfoDd(userAddress, true);
  const phoneLabel = createUserInfoDt("Phone");
  const phone = createUserInfoDd(user.phone);
  const websiteLabel = createUserInfoDt("Website");
  const website = createUserInfoDd(user.website);
  fullName.textContent = user.name;
  fullName.classList.add("user-info__title");
  userDetails.classList.add("user-info__body");
  userDetails.append(
    emailLabel,
    email,
    addressLabel,
    address,
    phoneLabel,
    phone,
    websiteLabel,
    website
  );
  return {
    title: fullName,
    body: userDetails,
  };
}
/**
 * Print the info for a given user.
 * @param {Integer} userId - The user id.
 */
async function printUserInfo(userId) {
  const api = `https://jsonplaceholder.typicode.com/users/${userId}`;
  const user = await fetchData(api).then((data) => data);
  const userInfo = document.querySelector(".user-info");
  const userInfoTemplate = getUserInfoTemplate(user);
  userInfo.hasChildNodes()
    ? userInfo.replaceChildren(userInfoTemplate.title, userInfoTemplate.body)
    : userInfo.append(userInfoTemplate.title, userInfoTemplate.body);
}
/**
 * Add a class "active" to a link.
 * @param {Integer} linkId - The link id.
 */
function addActiveClassTo(linkId) {
  const link = document.getElementById(linkId);
  link.classList.add("active");
}
/**
 * Print the user info on click.
 * @param {MouseEvent} e - The click event.
 * @param {NodeList} links - The users links.
 */
function handleClick(e, links) {
  e.preventDefault();
  const userId = e.target.id.split("user-")[1];
  const linkId = `user-${userId}`;
  history.pushState({ userId }, e.target.textContent, e.target.href);
  printUserInfo(userId);
  for (let i = 0; i < links.length; i++) {
    links[i].classList.remove("active");
  }
  addActiveClassTo(linkId);
}
/**
 * Listen all users links.
 */
function listenUsersLinks() {
  const usersLinks = document.querySelectorAll(".users-list__link");
  for (let i = 0; i < usersLinks.length; i++) {
    const link = usersLinks[i];
    link.addEventListener("click", (e) => handleClick(e, usersLinks));
  }
}
/**
 * Load user info when URL refers to an user page.
 */
function listenURL() {
  const currentURL = window.location.href;
  const isUserPage = currentURL.includes("user=");
  if (isUserPage) {
    const userId = currentURL.split("?user=")[1];
    const linkId = `user-${userId}`;
    printUserInfo(userId);
    addActiveClassTo(linkId);
  }
}
/**
 * Init the app.
 */
async function init() {
  const api = "https://jsonplaceholder.typicode.com/users";
  const users = await fetchData(api).then((data) => data);
  printUsersList(users);
  listenUsersLinks();
  listenURL();
}
init();