function applyAdapt(prefix, sibDisplay, user) {
  
  //- Allow to bind-user on selected attribute
  if (sibDisplay.getAttribute(prefix + "-user-id")) {
    sibDisplay.setAttribute(
      sibDisplay.getAttribute(prefix + "-user-id"),
      user["@id"]
    );
  }

  //- Allow to set data-src to a children sib-form
  if (sibDisplay.getAttribute(prefix + "-bind-resources")) {
    let form = sibDisplay.querySelector(
      sibDisplay.getAttribute(prefix + "-bind-resources") + " sib-form"
    );
    if (form) {
      form.setAttribute(
        "data-src",
        sibDisplay.component.resourceId.replace("members/", "")
      );
    }
  }

  //- Allow to put user on a targetted search field
  if (sibDisplay.getAttribute(prefix + "-bind-user2input")) {
    sibDisplay.querySelector(
      sibDisplay.getAttribute(prefix + "-bind-user2input")
    ).value = user["@id"];
  }
}

function recursiveAdaptWidgets(prefix, element, user) {
  
  element.addEventListener("populate", () => {
    
    //- This function is a workaround for the currently unworking populate
    //- Feel free to see examples on page-circles-
    element.querySelectorAll("[" + prefix + "-user-id]").forEach(el => {
      el.setAttribute(el.getAttribute(prefix + "-user-id"), user["@id"]);
    });
    applyAdapt(prefix, element, user);

    document.querySelectorAll('sib-display, sib-form').forEach(sibDisplay => {
      applyAdapt(prefix, sibDisplay, user);
    });
  });
}

// auxiliary function closes the user profile menu
function closeUserControls() {
  let userControls = document.querySelector("#user-controls");
  if (userControls) userControls.removeAttribute("open");
}

function closeLeftMenu() {
  let leftMenu = document.querySelector("#main__menu");
  if (leftMenu) leftMenu.removeAttribute("open");
}

function closeRightMenu() {
  let rightMenu = document.querySelectorAll(".jsRightMenu");
  if (Array.from(rightMenu).filter(el => el.hasAttribute("open")).length > 0) {
    Array.from(document.querySelectorAll(".views-container")).forEach(vC =>
      vC.classList.toggle("sidebar-is-closed")
    );
    Array.from(rightMenu).forEach(el => el.removeAttribute("open"));
  }
}

function openRightMenu() {
  let rightMenu = document.querySelectorAll(".jsRightMenu");
  Array.from(rightMenu).forEach(el => el.setAttribute("open", ""));
  Array.from(document.querySelectorAll(".views-container")).forEach(vC =>
    vC.classList.toggle("sidebar-is-closed")
  );
}

//auxiliary function clears cache & refreshes sib-displays for a given resource ID
function refreshSibDisplays(resourceId, clearCache = true) {
  let cacheCleared = false;

  Array.from(document.querySelectorAll("sib-display"))
    .filter(sibDisplay => sibDisplay.component.resourceId == resourceId) // keep only elements with resource == edited resource
    .forEach(e => {
      //clear cache if we were unable to before
      if ((clearCache && !cacheCleared) && e.component.resource != null) {
        e.component.resource.clearCache();
        cacheCleared = true;
      }
      e.dataset.src = e.dataset.src;
    }); // and update them
}

//auxiliary function updates displays using a given resource
//NOTE: this is a temporary workaround and should be replaced by a reactive storage
//https://git.happy-dev.fr/startinblox/framework/sib-core/issues/524
async function refreshResource(event) {

  // if of the edited resource || id of the container of the created resource
  const resourceId = event.detail.resource["@id"] || event.target.dataset.src;
  let resource = document
    .querySelector('[data-src="' + resourceId + '"]')
    .component.resource.getResourceData();

  //special case: refresh circles/X/ from circle-members/Y/
  let partnerId = null;
  if (resourceId.includes("circle-members")) {
    partnerId = resource["http://happy-dev.fr/owl/#circle"]["@id"];
  } else if (resourceId.includes("project-members"))
    partnerId = resource["http://happy-dev.fr/owl/#project"]["@id"];
  
  //refresh all resources using the partner ID
  if (partnerId != null) {
    refreshSibDisplays(partnerId);
    refreshSibDisplays(partnerId + "members/");
  }

  //special cases updating users/X/circles for the left-side-menu (leaving or joining circle)
  let user = await document.querySelector('sib-auth').getUser();
  if(resourceId.includes('circle') && user != null) {
    let userId = user['@id'];
    refreshSibDisplays(userId + "circles/");
    refreshSibDisplays(resourceId.split('/').slice(0,4).join('/')+'/joinable/');
  }

  //clear cache on this resource
  //NOTE: this is required because the cache is not refreshed after POSTing changes on the resource
  let cacheCleared = false;
  if (event.target.component.resource != null) {
    event.target.component.resource.clearCache();
    cacheCleared = true;
  }

  //update all displays which use this resource
  refreshSibDisplays(resourceId, cacheCleared);
}

//auxiliary function performs a redirect
//NOTE: currently a sib-display is required to dispatch the requestNavigation event
function performRedirect(route) {
  document.dispatchEvent(
    new CustomEvent("requestNavigation", {
      bubbles: true,
      detail: { route: route }
    })
  );
}

//auxiliary function redirects after leaving a project/circle
//NOTE: this is a temporary workaround until the following issues are resolved:
//https://git.happy-dev.fr/startinblox/framework/sib-core/issues/476
//https://git.happy-dev.fr/startinblox/framework/sib-core/issues/546
async function checkForPostLeaveRedirect(event) {
  //a redirect will only be required if I left in the information page of the resource
  if(!window.location.href.includes('-information')) return;
  //first need to get a sib-display with this resource id (to have access to the target Proxy, containing model fields)
  const resourceId = event.detail.resource['@id'] || event.target.dataset.src;
  let target = document.querySelector('[data-src="' + resourceId + '"]');
  let resource = target.component.resource.getResourceData();

  //no redirect is required for public circles
  let targetCircleId = resource["http://happy-dev.fr/owl/#circle"]["@id"];
  if(targetCircleId != undefined) {
    let targetCircle = document.querySelector('[data-src="' + targetCircleId + '"]');
    let targetCircleResource = targetCircle.component.resource.getResourceData();
    if(targetCircleResource['http://happy-dev.fr/owl/#status'] == 'Public') return;
  }

  //a redirect will only be required if I've deleted myself
  let targetUser = resource['http://happy-dev.fr/owl/#user'];

  //compare with current user
  let user = await document.querySelector('sib-auth').getUser();
  if(targetUser['@id'] != user['@id'] && targetUser['@id'] != undefined) return;

  //perform the redirect
  if(resourceId.includes('circle')) performRedirect('circle-left');
  else if(resourceId.includes('project')) performRedirect('project-left');
}

//- Update badges from notifications list
async function updateBadges(element) {
  const unreadNotifications = new Map();
  const notifications = element.component.resource;
  if (!notifications) return;
  // Generate unread map
  for (let notification of notifications['ldp:contains']) {
    if (await notification['unread']) {
      const object = await notification['object'];
      unreadNotifications.set(object['@id'], (unreadNotifications.get(object['@id']) || 0) + 1);
    }
  }
  // update badges
  unreadNotifications.forEach((notifNumber, objectId) => {
    const badge = document.querySelector(`sib-fix-badge[data-src="${objectId}"]`);
    if (badge) {
      badge.innerText = notifNumber || '';
      badge.style.display = notifNumber ? 'block' : 'none';
    }
  })
}

document.addEventListener("DOMContentLoaded", function(event) {
  const menuWrappers = Array.from(document.querySelectorAll(".menu-wrapper"));

  //- View change event
  window.addEventListener("navigate", event => {
    closeLeftMenu();
    closeUserControls();
  });

  //- Toggle sub-menus
  menuWrappers.forEach(menuWrapper => {
    const menu = menuWrapper.querySelector(".menu");
    menu.addEventListener("click", e => {
      menuWrapper.classList.toggle("is-closed");
    });
  });

  //- Watch every sib-forms & update data-src of linked sib-display
  document.querySelector("body").addEventListener("save", event => {
    refreshResource(event);
  });
  document.querySelector("body").addEventListener("resourceDeleted", event => {
    //I might need to be redirected from this page
    checkForPostLeaveRedirect(event).then(refreshResource(event));
  });

  document
    .querySelector("sib-auth")
    .getUser()
    .then(user => {
      if (user !== null) {
        document
          .querySelectorAll(".notLoggedIn")
          .forEach(el => (el.style.visibility = "visible"));
        // Hide login button if already logged
        document
          .querySelector('.loggedIn')
          .setAttribute("style", "display:none !important");
        document.querySelectorAll('sib-display, sib-form').forEach(element => {
          // Set current user id on set-user-id of sib-display
          recursiveAdaptWidgets("hd-inherit", element, user);
        });
        for (leaveBtn of document.querySelectorAll(
          "admin-circle-leave > sib-ac-checker:not([hidden])"
        )) {
          leaveBtn.parentNode.parentNode.parentNode.nextElementSibling.setAttribute(
            "style",
            "display:none !important"
          ); // Hide Join button
        }
      } else {
        document.querySelector('sib-auth').login();
      }
    })
    .catch(error => console.log(error));

  // Document -> close menu
  document.addEventListener("click", event => {
    if (!event.target.closest("#user-controls")) {
      closeUserControls();
    }
    if (
      !event.target.closest("#main__menu") &&
      event.target.id != "toggleMainMenu"
    ) {
      closeLeftMenu();
    }
    if (
      !event.target.className.includes("jsMobileSidebarOpenButton") &&
      !event.target.className.includes("jsOffsiteToggle")
    ) {
      closeRightMenu();
    }
  });

  document.querySelector("#toggleMainMenu").addEventListener("click", event => {
    let leftMenu = document.querySelector("#main__menu");
    if (leftMenu.hasAttribute("open")) {
      closeLeftMenu();
    } else {
      leftMenu.setAttribute("open", "");
    }
  });

  Array.from(document.querySelectorAll(".jsMobileSidebarOpenButton")).forEach(
    el => {
      el.addEventListener("click", event => {
        openRightMenu();
      });
    }
  );

  const rightMenus = Array.from(document.querySelectorAll("nav.jsRightMenu"));
  rightMenus.forEach(rightMenu => {
    const btnRightMenu = rightMenu.querySelector("li.jsOffsiteToggle");
    btnRightMenu.addEventListener("click", e => {
      if (rightMenu.hasAttribute("open")) {
        closeRightMenu();
      } else {
        openRightMenu();
      }
    });
  });

  // listen for keypress
  document.onkeydown = e => {
    e = e || window.event;
    if (e.key === "Escape" || e.key === "Esc") {
      closeUserControls();
      closeLeftMenu();
      closeRightMenu();
    }
  };

  //- Fix badges performances
  // on load time
  document.getElementById('notifications-list').addEventListener('populate', (event) => {
    const checkExist = setInterval(function () { // wait for left menus to exist
      const subMenus = document.querySelectorAll('.sub-menu > sib-display > div');
      if (subMenus.length >= 2) {
        updateBadges(event.target);
        clearInterval(checkExist);
      }
    }, 500);
  }, { once: true });

  // on refresh notification list
  window.addEventListener('notificationsRefresh', () => {
    document.getElementById('notifications-list').addEventListener('populate', (event) => {
      updateBadges(event.target);
    }, { once: true });
  });

  // on read notification
  window.addEventListener('read', (event) => {
    if (event.detail && event.detail.resource && event.detail.resource['@id']) {
      const badge = document.querySelector(`sib-fix-badge[data-src="${event.detail.resource['@id']}"]`);
      if (badge) badge.style.display = "none";
    }
  });

});
