{% macro appCard(app, infos, timestamp_now, catalog) -%}

{% set this_app_stars = stars.get(app, {})|length %}
{% if user %}
    {% set user_starred_this_app = user['id'] in stars.get(app, {}) %}
{% else %}
    {% set user_starred_this_app = False %}
{% endif %}

<div class="search-entry"
     data-appid="{{ app }}"
     data-stars="{{ this_app_stars }}"
     data-starred="{{ user_starred_this_app }}"
     data-addedincatalog="{{ ((timestamp_now - infos['added_in_catalog']) / 3600 / 24) | int }}"
     data-category="{%- if infos['category'] -%}{{ infos['category'] }}{%- endif -%}"
>
    <a
        href="{{ url_for('app_info', app_id=app) }}"
        class="relative block overflow-hidden rounded-lg py-2 px-4 hover:bg-gray-100 mx-2 md:mx-0"
        >
        <div class="flex justify-between gap-4">
            <div class="shrink-0">
                <img alt="{{ _('Logo for %(app)s',app=infos['manifest']['name']) }}"
                     {% if infos['logo_hash'] %}
                     src="https://app.yunohost.org/default/v3/logos/{{ infos['logo_hash'] }}.png"
                     {% else %}
                     src="{{ url_for('static', filename='app_logo_placeholder.png') }}"
                     {% endif %}
                     loading="lazy"
                     class="h-12 w-12 rounded-lg object-cover shadow-sm mt-1"
                >
            </div>
            <div class="w-full">
                <span class="flex">
                    <h3 class="grow text-md font-bold text-gray-900">
                        {{ infos['manifest']['name'] }}
                    </h3>
                    <span class="text-xs">
                        {% if infos['level'] == "?" or infos["level"]|int <= 4 %}
                        <i class="fa fa-exclamation-circle text-red-500 py-0.5"
                           aria-label="{{ _('This app is currently flagged as broken because it failed our automatic tests.') }} {{ _('This is usually a temporary situation which requires packagers to fix something in the app.') }}"
                           title="{{ _('This app is currently flagged as broken because it failed our automatic tests.') }} {{ _('This is usually a temporary situation which requires packagers to fix something in the app.') }}"
                        ></i>
                        {% elif infos['level'] == 8 %}
                        <i class="fa fa-diamond text-teal-500 py-0.5"
                           aria-label="{{ _('This app has been good quality according to our automatic tests over at least one year.') }}"
                           title="{{ _('This app has been good quality according to our automatic tests over at least one year.') }}"
                        ></i>
                        {% endif %}
                        <span class="inline-block group rounded-md text-xs text-violet-500 px-1 py-0.5">
                            <span class="inline-block">{{ this_app_stars }}</span>
                            <i class="fa {% if not user_starred_this_app %}fa-star-o{% else %}fa-star{% endif %} inline-block" aria-hidden="true"></i>
                        </span>
                    </span>
                </span>
                <p class="max-w-[40ch] text-xs text-gray-700">
                    {{ infos['manifest']['description']|localize }}
                </p>
                <div class="hidden">
                    {{ infos["potential_alternative_to"]|join(', ') }}
                </div>
                {% if infos['category'] %}
                <span class="rounded-full px-2.5 py-0.5 text-[10px]  border text-{{ catalog['categories'][infos['category']]['color'] }}-600 border-{{ catalog['categories'][infos['category']]['color'] }}-400 ">
                    {{ catalog['categories'][infos['category']]['title']|localize|lower }}
                </span>
                {% endif %}
            </div>
        </div>
    </a>
</div>
{%- endmacro %}

{% extends "base.html" %}
{% block title %}
{{ _("Application Catalog") }}
{% endblock %}
{% block main %}
<div class="mt-5 text-center">
    <h1 class="text-2xl font-bold text-gray-900">
        {{ _("Application Catalog") }} 
    </h1>
</div>
<div class="max-w-screen-md mx-auto mt-3 mb-3">
    <div class="flex flex-col md:flex-row items-center">
        <div class="px-2 inline-block relative basis-2/3 text-gray-700">
            <label for="search" class="sr-only"> {{ _("Search") }} </label>

            <input
                type="text"
                id="search"
                placeholder="{{ _('Search for…') }}"
              {% if init_search %}value="{{ init_search }}"{% endif %}
                class="w-full rounded-md border-gray-200 shadow-sm sm:text-sm py-2 pe-10"
            >

            <span class="absolute inset-y-0 end-0 grid w-10 place-content-center pr-4">
                <i class="fa fa-search" aria-hidden="true"></i>
            </span>
        </div>
        <div class="basis-1/3 px-2 pt-2 md:pt-0 md:px-0">

            <select
              name="selectcategory"
              id="selectcategory"
              class="w-full rounded-md border-gray-200 shadow-sm sm:test-sm px-2 py-1.5"
            >
            <option value="">{{ _("All apps") }}</option>
              {% for id, category in catalog['categories'].items() %}
                    <option {% if id == init_category %}selected{% endif %} value="{{ id }}">{{ category['title']|localize }}</option>
              {% endfor %}
            </select>
        </div>
    </div>

    <div class="flex flex-col md:flex-row justify-center items-center pt-2 text-center text-sm">
        <div class="inline-block px-2">
            {{ _("Sort by") }} 
            <select
              name="selectsort"
              id="selectsort"
              class="inline-block rounded-md border-gray-200 text-sm ml-1 pl-1 pr-7 h-8 py-0"
            >
            <option {% if not init_sort or init_sort == "popularity" %}selected{% endif %} value="popularity">{{ _("Popularity") }}</option>
            <option {% if init_sort == "newest" %}selected{% endif %} value="newest">{{ _("Newest") }}</option>
            <option {% if init_sort == "alpha" %}selected{% endif %} value="alpha">{{ _("Alphabetical") }}</option>
            </select>
        </div>
        <div class="inline-block flex items-center px-2 pt-2 md:pt-0 {% if not user %}text-gray-500{% endif %}" {% if not user %}title="{{ _('Requires to be logged-in') }}" aria-label="{{ _('Requires to be logged-in') }}"{% endif %}>
            <label for="starsonly" class="inline-block relative mr-2 h-4 w-7 cursor-pointer">
              <span class="sr-only">{{ _("Show only apps you starred") }}</span>
              <input type="checkbox" id="starsonly" class="peer sr-only" {% if user and init_starsonly %}checked{% endif %} {% if not user%}disabled{% endif %} >

              <span class="absolute inset-0 rounded-full bg-gray-300 transition peer-checked:bg-green-500">
              </span>

              <span class="absolute inset-y-0 start-0 m-1 h-2 w-2 rounded-full bg-white transition-all peer-checked:start-3">
              </span>
            </label>
            {{ _("Show only apps you starred") }} 
        </div>
    </div>
</div>

<div id="catalogGoodQuality" class="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 max-w-screen-lg mx-auto pt-10">
    {% for app, infos in catalog['apps'].items() %}
        {% if infos['level'] and infos['level'] != "?" and infos['level'] > 4 and not "deprecated-software" in infos['antifeatures'] %}
            {{ appCard(app, infos, timestamp_now, catalog) }}
        {% endif %}
    {% endfor %}
</div>


<div id="noResultFound" class="text-center pt-5 hidden">
    <p class="text-lg font-bold text-gray-900 mb-5">
        {{ _("No results found.") }} 
    </p>
    <p class="text-md text-gray-900">
        {{ _("Not finding what you are looking for?") }}<br/>
        {{ _("Checkout the wishlist!") }} 
    </p>
</div>


<div id="lowQualityAppTitle" class="text-center pt-10 mx-4 md:mx-0">
    <h2 class="text-lg font-bold text-gray-900">
        {{ _("Applications currently flagged as broken") }} 
    </h2>
    <p class="text-sm">
        {{ _("These are apps which failed our automatic tests.") }}<br/>
        {{ _("This is usually a temporary situation which requires packagers to fix something in the app.") }} 
    </p>
</div>

<div id="catalogLowQuality" class="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 max-w-screen-lg mx-auto pt-10">
    {% for app, infos in catalog['apps'].items() %}
        {% if not infos['level'] or infos["level"] == "?" or infos['level']  <= 4 %}
            {{ appCard(app, infos, timestamp_now, catalog) }}
        {% endif %}
    {% endfor %}
</div>

<div id="deprecatedAppTitle" class="text-center pt-10 mx-4 md:mx-0">
    <h2 class="text-lg font-bold text-gray-900">
        {{ _("Deprecated applications") }} 
    </h2>
    <p class="text-sm">
        {{ _("These are apps who are not maintained anymore.") }}<br/>
        {{ _("This means that the developer will no longer update them. We strongly advise against their installation and advise users to find alternatives.") }} 
    </p>
</div>

<div id="catalogDeprecated" class="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 max-w-screen-lg mx-auto pt-10">
    {% for app, infos in catalog['apps'].items() %}
        {% if "deprecated-software" in infos['antifeatures'] %}
            {{ appCard(app, infos, timestamp_now, catalog) }}
        {% endif %}
    {% endfor %}
</div>


<script type="text/javascript">
    // A little delay
    let typingTimer;
    let typeInterval = 500; // Half a second
    let searchInput = document.getElementById('search');
    let selectCategory = document.getElementById('selectcategory');
    let selectSort = document.getElementById('selectsort');
    let toggleStarsonly = document.getElementById('starsonly');

    function liveSearch() {
        // Locate the card elements
        let entries = document.querySelectorAll('.search-entry')
        // Locate the search input
        let search_query = searchInput.value.trim().toLowerCase();
        let selectedCategory = selectCategory.value.trim();
        let starsOnly = toggleStarsonly.checked;
        let at_least_one_match = false;
        // Loop through the entries
        for (var i = 0; i < entries.length; i++) {
            // If the text is within the card and the text matches the search query
            if ((entries[i].textContent.toLowerCase().includes(search_query))
                && (! selectedCategory || (entries[i].dataset.category == selectedCategory))
                && (! starsOnly || (entries[i].dataset.starred == "True")))
            {
                // ...remove the `.is-hidden` class.
                entries[i].classList.remove("hidden");
                at_least_one_match = true;
            }
            else
            {
                // Otherwise, add the class.
                entries[i].classList.add("hidden");
            }
        }

        if (at_least_one_match === false)
        {
            document.getElementById('lowQualityAppTitle').classList.add("hidden");
            document.getElementById('noResultFound').classList.remove("hidden");
        }
        else
        {
            document.getElementById('lowQualityAppTitle').classList.remove("hidden");
            document.getElementById('noResultFound').classList.add("hidden");
        }

        updateQueryArgsInURL()
    }

    function liveSort(container_to_sort) {
        let sortBy = selectSort.value.trim();
        var toSort = document.getElementById(container_to_sort).children;
        toSort = Array.prototype.slice.call(toSort, 0);
        if (sortBy === "newest") {
            toSort.sort(function(a, b) {
                return a.dataset.addedincatalog - b.dataset.addedincatalog;
            });
        }
        else if (sortBy === "popularity") {
            toSort.sort(function(a, b) {
                return parseInt(a.dataset.stars) < parseInt(b.dataset.stars) ? 1 : -1;
            });
        }
        else if (sortBy === "alpha") {
            toSort.sort(function(a, b) {
                return a.dataset.appid > b.dataset.appid ? 1 : -1;
            });
        }
        var parent = document.getElementById(container_to_sort);
        parent.innerHTML = "";

        for(var i = 0, l = toSort.length; i < l; i++) {
            parent.appendChild(toSort[i]);
        }

        updateQueryArgsInURL()
    }

    function updateQueryArgsInURL() {
        let search_query = searchInput.value.trim();
        let category = selectCategory.value.trim();
        let sortBy = selectSort.value.trim();
        let starsOnly = toggleStarsonly.checked;

        if ('URLSearchParams' in window) {
            var queryArgs = new URLSearchParams(window.location.search)
            if (search_query) { queryArgs.set("search", search_query) } else { queryArgs.delete("search"); };
            if (category) { queryArgs.set("category", category) } else { queryArgs.delete("category"); };
            if (sortBy != "popularity") { queryArgs.set("sort", sortBy) } else { queryArgs.delete("sort"); };
            if (starsOnly) { queryArgs.set("starsonly", true) } else { queryArgs.delete("starsonly"); };

            let newUrl;
            if (queryArgs.toString())
            {
                newUrl = window.location.pathname + '?' + queryArgs.toString();
            }
            else
            {
                newUrl = window.location.pathname;
            }

            if (newUrl != window.location.pathname + window.location.search)
            {
                history.pushState(null, '', newUrl);
            }
        }
    }

    searchInput.addEventListener('keyup', () => {
      clearTimeout(typingTimer);
      typingTimer = setTimeout(liveSearch, typeInterval);
    });

    selectCategory.addEventListener('change', () => {
      clearTimeout(typingTimer);
      typingTimer = setTimeout(liveSearch, typeInterval);
    });

    selectSort.addEventListener('change', () => {
      liveSort("catalogGoodQuality");
      liveSort("catalogLowQuality");
    });

    toggleStarsonly.addEventListener('change', () => {
      clearTimeout(typingTimer);
      typingTimer = setTimeout(liveSearch, typeInterval);
    });

    liveSearch();
    liveSort("catalogGoodQuality");
    liveSort("catalogLowQuality");

</script>

{% endblock %}
