
/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import debounce from "lodash/debounce";
import shuffle from "lodash/shuffle";

function handleIntegration() {
  const root = document.querySelector("#integrations");

  if (!root) {
    return;
  }

  const templateText = root.querySelector("#integration-template").innerText;
  const templateElement = document.createElement("div");
  templateElement.innerHTML = templateText;

  const loadingIndicator = root.querySelector(".loading");
  const listItems = root.querySelector(".list-items");
  const searchBox = root.querySelector('[type="search"]');
  const moreButton = root.querySelector("#show-more-integration");

  let currentPage = 1;
  let currentQuery = "";
  const maxItemsOnPage = window.innerWidth < 1920 ? 8 : 10;

  function setIndicatorVisibility(visible) {
    loadingIndicator.style.display = visible ? "" : "none";
    listItems.style.display = visible ? "none" : "";
  }
  setIndicatorVisibility(false);

  function setMoreButtonVisibility(visible) {
    moreButton.style.display = visible ? "" : "none";
  }
  setMoreButtonVisibility(true);

  const sortByLogoAvailability = (a, b) => {
    const a_key = a.logo ? 1 : -1;
    const b_key = b.logo ? 1 : -1;
    return b_key - a_key;
  };

  let fetchIntegrationRequest = null;

  function fetchIntegration() {
    if (fetchIntegrationRequest) {
      return fetchIntegrationRequest;
    }
    const request = Promise.all([
      fetch("/integrations.json"),
      () => {
        setIndicatorVisibility(true);
      }
    ])
      .then(([resp]) => resp.json())
      .then((integrations) => {
        setIndicatorVisibility(false);
        return Promise.resolve(integrations);
      })
      .then((integrations) => {
        integrations = shuffle(integrations);
        integrations.sort(sortByLogoAvailability);
        integrations.forEach((i, index) => i.inddex = index);
        return Promise.resolve(integrations);
      });
    fetchIntegrationRequest = request;
    return request;
  }

  function createElement(item) {
    const element = templateElement.cloneNode(true);

    const imgNode = element.querySelector('[data-name="logo"]');
    if (item.logo) {
      imgNode.src = item.logo;
      imgNode.alt = `${item.name} logo`;
    } else {
      imgNode.parentNode.removeChild(imgNode);
    }

    element.querySelector('[data-name="name"]').innerText = item.name;
    element.querySelector("a").href = item.url;
    return element.firstElementChild;
  }

  function setItems(items) {
    if (items.length === 0) {
      listItems.innerText = "No items";
    } else {
      while (listItems.firstChild) {
        listItems.removeChild(listItems.firstChild);
      }
      items.forEach((item) => {
        const element = createElement(item);
        listItems.append(element);
      });
    }
  }

  function showItems(keyword, page) {
    const showMoreButtonIfNeeded = (integrations) => {
      setMoreButtonVisibility(integrations.length > (page * maxItemsOnPage));
    };

    const filterMatchingItems = (integrations) => {
      if (!keyword) {
        return Promise.resolve(integrations);
      }
      const selectedIntegration = integrations.filter(
        (integration) => integration.name.toLowerCase().indexOf(keyword.toLowerCase()) >= 0
      );
      return Promise.resolve(selectedIntegration);
    };

    const filterVisible = (integrations) => {
      return Promise.resolve(integrations.slice(0, page * maxItemsOnPage));
    };

    const itemsPromise = fetchIntegration()
      .then(filterMatchingItems);
    itemsPromise.then(filterVisible).then(setItems);
    itemsPromise.then(showMoreButtonIfNeeded);
  }

  function setSearchQuery(keyword) {
    currentQuery = keyword;
    showItems(currentQuery, currentPage);
  }

  searchBox.addEventListener("keyup", debounce(function() {
    currentPage = 1;
    setSearchQuery(searchBox.value);
  }, 0));

  moreButton.addEventListener("click", function() {
    currentPage = currentPage + 1;
    setSearchQuery(searchBox.value);
  });

  setSearchQuery("");
}

handleIntegration();
