<!-- Package Grid -->

<section>
  <div class="container black-bg">
    <div class="row">
      <div class="col">
        {{- partial "search-menu.html" "searchTermDesktop" -}}
        <hr>

        <div class="package-grid">

          <!-- Start Package Grid -->

          <div class="row package-row black-bg g-0">
            <div id="packageGrid" class="package-grid">
              {{ range $.Site.Data.packages }}
                {{- partial "package-thumbnail.html" .}}
              {{ end }}
            </div>
            {{- partial "no-results-found.html" }}
          </div>
        </div>
        <hr>
        <div id="loadMoreSection" class="container small">
          <div id="loadMorePackagesBtn"><i class="icon-enter-arrow"></i> SHOW MORE</div>
        </div>
      </div>
    </div>
  </div>
</section>

<style>
  .container.small {
    padding-top: 1em;
    padding-bottom: 1em;
  }
  .package-grid {
    display: grid;
    grid-template-columns: auto;
  }
  #loadMorePackagesBtn {
    cursor: pointer;
    font-size: 2rem;
    font-family: "pp-neue-machina", sans-serif;
    background-color: #1a1a1a;
    color: #fff;
    padding-top: 0.279vw;
    text-decoration: none;
    text-transform: uppercase;
    transition: 0.1s linear;
  }
  #loadMorePackagesBtn .icon-enter-arrow {
    display: inline-block;
    position: relaitve;
    transition: all 0.2s ease-in-out;
  }
  #loadMorePackagesBtn:hover .icon-enter-arrow{
    display: inline-block;
    transform: rotate(-45deg) !important;
  }
  #loadMoreSection.hidden {
    display: none;
  }
  @media only screen and (max-width: 576px) {
    #loadMoreSection {
      display: none;
    }
  }

  @media only screen and (min-width: 576px) {
    .package-grid {
      /* changes to 3 column thumbs */
      grid-template-columns: auto auto auto;
    }
  }

  @media only screen and (min-width: 992px) {
    .package-grid {
      /* changes to 4 column thumbs */
      grid-template-columns: auto auto auto auto;
    }
  }

  .card-thumbnail.hidden {
    height: 0px;
    padding: 0px;
    margin: 0px;
    border: 0px;
    overflow: hidden;
  }
</style>
<script async src="https://unpkg.com/string-similarity@4.0.1/umd/string-similarity.min.js"></script>
<script language="javascript" type="text/javascript">
  const sortOptions = {
    popularity: 'popularity',
    last_modified: 'last_modified',
  }
  const showAllPackages = window.location.pathname.includes("/+/");

  let sortBy = sortOptions.popularity; // last_modified
  let sortDirection = 'desc'; // asc
  let limit = 16;

  const grid = document.getElementById('packageGrid');
  const packagesCache = Array.from(grid.children).filter((e) => e.dataset && e.dataset.name);

  function debounce(fn, delay) {
    var timer = null;
    return function () {
      var context = this, args = arguments;
      clearTimeout(timer);
      timer = setTimeout(function () {
        fn.apply(context, args);
      }, delay);
    };
  }

  const onSearch = debounce(() => {
    const searchInput = document.getElementById('searchTermDesktop');
    const noResult = document.getElementById('noResult');
    if (searchInput.value) {
      const term = searchInput.value;
      const packages = getPackageThumbs();
      for(let pkg of packages) {
        pkg.match_score = getMatchScore(term, pkg.dataset);
      }
      const sortedPackages = packages.sort((a, b) => {
        return b.match_score - (a ? a.match_score : 0);
      });

      const grid = document.getElementById('packageGrid');
      grid.textContent = '';
      let searchCount = 0;
      for(const sp of sortedPackages) {
        const score = getMatchScore(term, sp.dataset);
        if (score > 20) {
          sp.classList.remove('hidden');
          searchCount++;
        } else {
          sp.classList.add('hidden');
        }
        grid.appendChild(sp);
      }

      if (searchCount) {
        loadMoreSection.classList.remove('hidden');
        noResult.classList.remove('show');
      } else {
        loadMoreSection.classList.add('hidden');
        noResult.classList.add('show');
      }

    } else {
      noResult.classList.remove('show');
      sortPackages();
    }
  }, 300);

  const searchInputDesktop = document.getElementById('searchTermDesktop');
  searchInputDesktop.addEventListener("search", onSearch);
  searchInputDesktop.addEventListener("change", onSearch);
  searchInputDesktop.addEventListener("keyup", onSearch);

  function getPackageThumbs() {
    // const grid = document.getElementById('packageGrid');
    return packagesCache;
  }

  const packagesCount = getPackageThumbs().length;

  function sortPackages() {
    const packages = getPackageThumbs();
    const sortedPackages = packages.sort((a, b) => {
      if (sortBy === sortOptions.popularity) {
        const aPop = +a.dataset.popularity;
        const bPop = +b.dataset.popularity;
        return sortDirection === 'asc' ? aPop-bPop : bPop - aPop;
      } else { // last_modified
        const aDate = new Date(a.dataset.last_modified);
        const bDate = new Date(b.dataset.last_modified);
        return sortDirection === 'asc' ? aDate-bDate : bDate - aDate;
      }
    });

    const grid = document.getElementById('packageGrid');
    grid.textContent = '';

    for(const sp of sortedPackages) {
      grid.appendChild(sp);
    }

    const isPopularity = sortBy === sortOptions.popularity;

    setBtnStyles(sortOptions.popularity, isPopularity);
    setBtnStyles(sortOptions.last_modified, !isPopularity);
    refreshDisplayedPackages();
  }

  function refreshDisplayedPackages() {
    const packages = getPackageThumbs();
    let i = 0;
    for(const sp of packages) {
      if (i >= limit && !showAllPackages) {
        sp.classList.add('hidden');
      } else {
        sp.classList.remove('hidden');
      }
      i++;
    }
  }

  function getMatchScore(term, dataset) {
    // provide higher value with name
    const { name, maintainer, description } = dataset;
    const exactMatch = [maintainer, name].join(" ").toLocaleLowerCase().includes(term.toLocaleLowerCase());
    const nameScore = stringSimilarity.compareTwoStrings(name, term);
    const descriptionScore = stringSimilarity.compareTwoStrings(description, term);
    return (nameScore*80) + (descriptionScore*20) + (exactMatch ? 100 : 0);
  }

  const loadMoreButton = document.getElementById('loadMorePackagesBtn');
  if (showAllPackages) {
    loadMoreSection.classList.add('hidden');
  } else {
    loadMoreSection.classList.remove('hidden');
  }
  loadMoreButton.addEventListener('click',() => {
    limit += 16;
    refreshDisplayedPackages();
    if (limit >= packagesCount) {
      const loadMoreSection = document.getElementById('loadMoreSection');
      loadMoreSection.classList.add('hidden');
    }
  }, false);

  function getSortBtns(type) {
    const typeBtn = document.getElementById(`dropdown-${type}-btn`);
    const typeDownBtn = document.getElementById(`${type}-down-btn`);
    const typeUpBtn = document.getElementById(`${type}-up-btn`);
    return { typeBtn, typeDownBtn, typeUpBtn };
  }

  function setBtnStyles(type, active) {
    const { typeBtn, typeDownBtn, typeUpBtn } = getSortBtns(type);
    if (active) {
      typeBtn.classList.add('active');
      if (sortDirection === 'asc') {
        typeUpBtn.classList.add('active');
        typeDownBtn.classList.remove('active');
      } else {
        typeDownBtn.classList.add('active');
        typeUpBtn.classList.remove('active');
      }
    } else {
      typeBtn.classList.remove('active');
      typeDownBtn.classList.remove('active');
      typeUpBtn.classList.remove('active');
    }
  }

  function configureSortButton(type) {
    const { typeBtn, typeDownBtn, typeUpBtn } = getSortBtns(type);
    typeBtn.addEventListener('click',() => {
      if (sortBy != type) {
        sortBy = type;
        sortPackages();
      }
    }, false);

    typeDownBtn.addEventListener('click',() => {
      if (sortBy != type || sortDirection != 'desc') {
        sortBy = type;
        sortDirection = 'desc';
        sortPackages();
      }
    }, false);

    typeUpBtn.addEventListener('click',() => {
      if (sortBy != type || sortDirection != 'asc') {
        sortBy = type;
        sortDirection = 'asc';
        sortPackages();
      }
    }, false);
  }

  configureSortButton(sortOptions.popularity);
  configureSortButton(sortOptions.last_modified);

  sortPackages();
</script>
