{%- extends 'base.html' -%}
{%- block content -%}
{%- set tips = [
    _("Changedetection.io can monitor more than just web-pages! See our plugins!") ~ ' <a href="https://changedetection.io/plugins">' ~ _('More info') ~ '</a>',
    _("You can also add 'shared' watches.") ~ ' <a href="https://github.com/dgtlmoon/changedetection.io/wiki/Sharing-a-Watch">' ~ _('More info') ~ '</a>'
] -%}
{%- from '_helpers.html' import render_simple_field, render_field, render_nolabel_field, sort_by_title -%}
<script src="{{url_for('static_content', group='js', filename='jquery-3.6.0.min.js')}}"></script>
<script src="{{url_for('static_content', group='js', filename='watch-overview.js')}}" defer></script>
<script src="{{url_for('static_content', group='js', filename='restock-price-graph.js')}}" defer></script>
<script src="{{url_for('static_content', group='js', filename='modal.js')}}"></script>
<script>let nowtimeserver={{ now_time_server }};</script>
<script>let favicon_baseURL="{{ url_for('static_content', group='favicon', filename="PLACEHOLDER")}}";</script>
<script>
// Cross-page selection: total rows matching the current filter, and the endpoint
// that lists all matching UUIDs for the "select all matching" action.
window.watchListSelection = {
    total: {{ pagination.total }},
    uuidsUrl: "{{ url_for('watchlist.uuids') }}"
};
</script>
<script>
document.addEventListener('DOMContentLoaded', function() {
    // (Feather icons are rendered app-wide from base.html.)

    // Placeholder shown when a favicon fails to load (network error, or the URL
    // returned HTML instead of an image etc). Same round outline as the loading
    // placeholder, but with a small red dot to signify the error state.
    const FAVICON_ERROR_SRC = 'data:image/svg+xml;utf8,' +
        '%3Csvg xmlns="http://www.w3.org/2000/svg" width="7.087" height="7.087" viewBox="0 0 7.087 7.087"%3E' +
        '%3Ccircle cx="3.543" cy="3.543" r="3.279" stroke="%23e1e1e1" stroke-width="0.45" fill="none" opacity="0.74"/%3E' +
        '%3Ccircle cx="5.4" cy="5.4" r="0.7" fill="%23d9534f"/%3E' +
        '%3C/svg%3E';

    // Load the real favicon URL stored in data-src, falling back to an error
    // placeholder (and a console error) if the image can't be loaded.
    function loadFavicon(img) {
        const src = img.getAttribute('data-src');
        if (!src) {
            return;
        }
        img.removeAttribute('data-src');
        img.addEventListener('error', function onError() {
            img.removeEventListener('error', onError);
            console.error('Favicon failed to load (network error or non-image response):', src);
            img.src = FAVICON_ERROR_SRC;
        });
        img.src = src;
    }

    // Intersection Observer for lazy loading favicons
    // Only load favicon images when they enter the viewport
    if ('IntersectionObserver' in window) {
        const faviconObserver = new IntersectionObserver((entries, observer) => {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    loadFavicon(entry.target);

                    // Stop observing this image
                    observer.unobserve(entry.target);
                }
            });
        }, {
            // Start loading slightly before the image enters viewport
            rootMargin: '50px',
            threshold: 0.01
        });

        // Observe all lazy favicon images
        document.querySelectorAll('.lazy-favicon').forEach(img => {
            faviconObserver.observe(img);
        });
    } else {
        // Fallback for older browsers: load all favicons immediately
        document.querySelectorAll('.lazy-favicon').forEach(loadFavicon);
    }
});
</script>
<style>
.checking-now .last-checked {
    background-image: linear-gradient(to bottom, transparent 0%, rgba(0,0,0,0.05) 40%, rgba(0,0,0,0.1) 100%);
    background-size: 0 100%;
    background-repeat: no-repeat;
    transition: background-size 0.9s ease
}

/* Auto-generated processor badge colors */
{{ processor_badge_css|safe }}

/* Auto-generated tag colors */
{%- for uuid, tag in tags -%}
    {%- if tag and tag.title -%}
    {%- set class_name = tag.title|sanitize_tag_class -%}
    {#- Anything but a hex colour would inject CSS rules here, fall back to the generated colour -#}
    {%- set tag_colour = tag.get('tag_colour')|safe_css_colour -%}
        {%- if tag_colour -%}
            .button-tag.tag-{{ class_name }},
            .watch-tag-list.tag-{{ class_name }} {
              background-color: {{ tag_colour }};
              color: {{ wcag_text_color(tag_colour) }};
            }
            {%- else -%}
                {%- set colors = generate_tag_colors(tag.title) -%}
                .button-tag.tag-{{ class_name }} {
                  background-color: {{ colors['light']['bg'] }};
                  color: {{ colors['light']['color'] }};
                }

                .watch-tag-list.tag-{{ class_name }} {
                  background-color: {{ colors['light']['bg'] }};
                  color: {{ colors['light']['color'] }};
                }

                html[data-darkmode="true"] .button-tag.tag-{{ class_name }} {
                  background-color: {{ colors['dark']['bg'] }};
                  color: {{ colors['dark']['color'] }};
                }

                html[data-darkmode="true"] .watch-tag-list.tag-{{ class_name }} {
                  background-color: {{ colors['dark']['bg'] }};
                  color: {{ colors['dark']['color'] }};
                }
            {%- endif -%}
        {%- endif -%}
    {%- endfor -%}
</style>

{% if llm_configured %}
<script>
window.watchOverviewI18n = {
    generatingSummary: {{ _('Generating change summary…')|tojson }},
    gotoHistory:       {{ _('Goto full history')|tojson }},
    loadingPriceHistory: {{ _('Loading price history…')|tojson }},
    inStock:           {{ _('In stock')|tojson }},
    outOfStock:        {{ _('Out of stock')|tojson }},
    noPriceData:       {{ _('No price data available to graph yet.')|tojson }},
    priceHistoryError: {{ _('Could not load price history.')|tojson }},
    changes:           {{ _('Changes')|tojson }},
    avgPrice:          {{ _('Average price')|tojson }},
    priceLow:          {{ _('Currently low')|tojson }},
    priceTypical:      {{ _('Currently typical')|tojson }},
    priceHigh:         {{ _('Currently high')|tojson }},
    cheaperThan:       {{ _('cheaper than %s% of tracked prices')|tojson }},
    pricierThan:       {{ _('more expensive than %s% of tracked prices')|tojson }},
    typicalNote:       {{ _('around the usual price')|tojson }},
    avgLabel:          {{ _('avg')|tojson }}
};
</script>
{% endif %}


<div class="box" id="add-watch-ui">
    <form class="pure-form" action="{{ url_for('ui.ui_views.form_quick_watch_add') }}" method="POST" id="new-watch-form">
        <div id="add-watch-url-row">
            <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
            <label for="url"><strong>{{ _('Web page URL') }}</strong></label><br>
            {{ render_nolabel_field(form.url, placeholder="https://...", required=true, class="pure-input-1") }}
            <button type="submit"  id="add-watch-go" class="pure-button pure-button-primary">{{ _('Watch') }}</button>
        </div>
        {% if llm_configured %}
        <div class="add-watch-option-group" id="quick-watch-llm-intent">
            <label for="quick_watch_llm_intent"><strong>{{ _('What matters — when to notify me') }}</strong></label>
            <textarea name="llm_intent"
                      id="quick_watch_llm_intent"
                      rows="4"
                      class="pure-input-1"
                      placeholder="{{ _('e.g. Notify me when products go in/out of stock, lead times change by more than a week, or new product variants appear. Skip review additions.') }}"></textarea>
        </div>
        {% endif %}
        <div class="add-watch-option-group" id="quick-watch-processor-type">
            {{ render_simple_field(form.processor) }}
        </div>
    </form>
</div>

<div class="box">
    <form class="pure-form" action="{{ url_for('ui.form_watch_list_checkbox_operations') }}" method="POST" id="watch-list-form">
    <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" >
    <input type="hidden" id="op_extradata" name="op_extradata" value="" >
    {# Option lists for the bulk Browser / Proxy modals (rendered by watch-overview.js into a ModalDialog).
       Mirrors the choices on the watch edit page. Kept inert inside <template> until the modal is opened. #}
    <template id="bulk-browser-options">
        <label class="bulk-choice-row"><input type="radio" name="bulk-fetch-backend" value="system" checked> {{ _('System settings default') }}</label>
        {% for key, label in available_fetchers %}
        <label class="bulk-choice-row"><input type="radio" name="bulk-fetch-backend" value="{{ key }}"> {{ label }}</label>
        {% endfor %}
    </template>
    {% if has_proxies %}
    <template id="bulk-proxy-options">
        <label class="bulk-choice-row"><input type="radio" name="bulk-proxy" value="" checked> {{ _('Default') }}</label>
        {% for key, meta in has_proxies.items() %}
        <label class="bulk-choice-row"><input type="radio" name="bulk-proxy" value="{{ key }}"> {{ meta.label }}</label>
        {% endfor %}
    </template>
    {% endif %}
    {# "Select all matching" banner — shown by watch-overview.js when the whole
       visible page is selected but more matching rows exist on other pages. #}
    <div id="select-all-banner" class="select-all-banner" style="display: none;"
         data-select-all-tmpl="{{ _('All %(page)s on this page are selected.') }}"
         data-select-all-action="{{ _('Select all %(total)s matching') }}"
         data-all-selected-tmpl="{{ _('All %(total)s matching are selected.') }}"
         data-clear-action="{{ _('Clear selection') }}"></div>

    <div id="stats_row">
        <div class="left">{%- if watches|length >= pagination.per_page -%}{{ pagination.info }}{%- endif -%}
            {# Live count of selected rows; %(count)s is filled (locale-formatted) by watch-overview.js #}
            <div id="records-selected" class="records-selected" data-template="{{ _('%(count)s records selected') }}" style="display: none;"></div>
        </div>
    </div>



    {%- if search_q -%}<div id="search-result-info">{{ _('Searching') }} "<strong><i>{{search_q}}</i></strong>"</div>{%- endif -%}


    {%- set sort_order = sort_order or 'asc' -%}
    {%- set sort_attribute = sort_attribute or 'last_changed'  -%}
    {%- set pagination_page = request.args.get('page', 0) -%}
    {%- set cols_required = 6 -%}
    {%- if any_has_restock_price_processor -%}
        {%- set cols_required = cols_required + 1 -%}
    {%- endif -%}
    {%- set wrapper_classes = [
        'has-unread-changes' if unread_changes_count else '',
        'has-error' if errored_count else '',
    ] -%}
    <div id="watch-table-wrapper" class="{{ wrapper_classes | reject('equalto', '') | join(' ') }}">
        <div id="tag-lister" class="{% if active_tag %}active-tag{% endif %}">
            <a id="tag-all" href="{{ filter_url(tag=None) }}" class="pure-button button-tag {{'active' if not active_tag_uuid }}">{{ _('All') }}</a>
            <!-- tag list -->
            {%- for uuid, tag in tags -%}
                {%- if tag != "" -%}
                    <a href="{{ filter_url(tag=uuid) }}" class="pure-button button-tag tag-{{ tag.title|sanitize_tag_class }} {{'active' if active_tag_uuid == uuid }}">{{ tag.title }}</a>
                {%- endif -%}
            {%- endfor -%}
        </div>

        <div id="list-related-buttons">
            {# Status-view filters as a segmented control. Counts are scoped to the
               current tag/processor/search context (computed in index()), so each
               option only appears when it has matches in the current view. #}
            <div class="seg" role="group" aria-label="{{ _('Filter watches') }}">
                <a class="{{ 'active' if not request.args.get('unread') and not request.args.get('with_errors') and not request.args.get('deals') }}"
                   href="{{ filter_url(unread=None, with_errors=None, deals=None) }}">{{ _('All') }}</a>
                {% if unread_count %}
                <a id="post-list-unread" class="{{ 'active' if request.args.get('unread') == '1' }}"
                   href="{{ filter_url(unread=1, with_errors=None, deals=None) }}">{{ _('Unread') }} <span class="seg-count seg-count--unread" id="unread-tab-counter">{{ unread_count|format_int_locale }}</span></a>
                {% endif %}
                {# Deals appears only when a price drop has been detected in the current view. #}
                {% if deals_count %}
                <a id="post-list-deals" class="{{ 'active' if request.args.get('deals') == '1' }}"
                   href="{{ filter_url(deals=1, unread=None, with_errors=None) }}">{{ _('Deals') }} <span class="seg-count seg-count--deal" id="deals-tab-counter">{{ deals_count|format_int_locale }}</span></a>
                {% endif %}
                {% if errored_count %}
                <a id="post-list-with-errors" class="{{ 'active' if request.args.get('with_errors') == '1' }}"
                   href="{{ filter_url(with_errors=1, unread=None, deals=None) }}">{{ _('With errors') }} <span class="seg-count seg-count--error" id="with-errors-tab-counter">{{ errored_count|format_int_locale }}</span></a>
                {% endif %}
            </div>
            {# Processor (watch type) filter — only when more than one type is in use.
               Counted over the current tag/search context; labels from the processor
               registry's short badge texts. #}
            {% if processor_counts|length > 1 %}
            <div class="seg" role="group" aria-label="{{ _('Filter by type') }}">
                <a class="{{ 'active' if not active_processor }}"
                   href="{{ filter_url(processor=None) }}">{{ _('All types') }}</a>
                {% for proc, label in processor_badge_texts.items() if proc in processor_counts %}
                <a class="{{ 'active' if active_processor == proc }}"
                   href="{{ filter_url(processor=proc) }}">{{ label }} <span class="seg-count">{{ processor_counts[proc]|format_int_locale }}</span></a>
                {% endfor %}
            </div>
            {% endif %}
            <div id="buttons-for-all-watches">
                {# Always rendered, hidden by CSS unless #watch-table-wrapper has .has-unread-changes.
                   It used to be {% if unread_count %}-gated, which meant it could not exist in the DOM
                   of another open tab — so marking viewed (or a new change arriving) in one tab could
                   never show/hide it in the other. Presence in the DOM is what lets realtime toggle it. #}
                {# Submit button rather than a link: these mutate state, so they must not be
                   reachable by GET (an <img src=...> would fire them). formaction/formmethod
                   retarget the enclosing #watch-list-form, whose csrf_token comes along - and
                   avoids a nested <form>, which is invalid HTML and silently dropped. #}
                <button type="submit" id="post-list-mark-views" class="cdio-btn"
                        formmethod="post" formaction="{{ filtered_action_url('ui.mark_all_viewed') }}"><i data-feather="eye"></i>{{ _('Mark all viewed') }}</button>
                <button type="submit" id="recheck-all" class="cdio-btn"
                        formmethod="post" formaction="{{ filtered_action_url('ui.form_watch_checknow') }}"><i data-feather="refresh-cw"></i>{{ _('Recheck all') }} {% if active_tag_uuid %}{{ _("in '%(title)s'", title=active_tag.title) }}{% endif %}</button>
            </div>
            <a title="{{ _('RSS Feed') }}" href="{{ url_for('rss.feed', tag=active_tag_uuid, token=app_rss_token)}}"><img alt="RSS Feed" id="feed-icon" src="{{url_for('static_content', group='images', filename='generic_feed-icon.svg')}}" height="15"></a>
        </div>

    <div id="checkbox-operations">
        <button type="button" class="pure-button button-secondary button-xsmall" id="check-invert"><i data-feather="repeat" ></i>&nbsp;{{ _('Invert') }}</button>
        <button class="pure-button button-secondary button-xsmall"  name="op" value="pause"><i data-feather="pause" ></i>&nbsp;{{ _('Pause') }}</button>
        <button class="pure-button button-secondary button-xsmall"  name="op" value="unpause"><i data-feather="play" ></i>&nbsp;{{ _('UnPause') }}</button>
        <button class="pure-button button-secondary button-xsmall"  name="op" value="mute"><i data-feather="volume-x" ></i>&nbsp;{{ _('Mute') }}</button>
        <button class="pure-button button-secondary button-xsmall"  name="op" value="unmute"><i data-feather="volume-2" ></i>&nbsp;{{ _('UnMute') }}</button>
        <button class="pure-button button-secondary button-xsmall" name="op" value="recheck"><i data-feather="refresh-cw" ></i>&nbsp;{{ _('Recheck') }}</button>
        <button class="pure-button button-secondary button-xsmall" name="op" value="assign-tag" id="checkbox-assign-tag"><i data-feather="tag" ></i>&nbsp;{{ _('Tag') }}</button>
        <button type="button" class="pure-button button-secondary button-xsmall" id="checkbox-set-browser"
                data-modal-title="{{ _('Set browser / fetch method for selected') }}"
                data-modal-apply="{{ _('Apply') }}"><i data-feather="globe" ></i>&nbsp;{{ _('Browser') }}</button>
        {% if has_proxies %}
        <button type="button" class="pure-button button-secondary button-xsmall" id="checkbox-set-proxy"
                data-modal-title="{{ _('Set proxy for selected') }}"
                data-modal-apply="{{ _('Apply') }}"><i data-feather="server" ></i>&nbsp;{{ _('Proxy') }}</button>
        {% endif %}
        {# Hidden real operation buttons triggered by the Browser/Proxy modals once a choice is made #}
        <button type="submit" name="op" value="set-fetch-backend" id="op-set-fetch-backend" hidden></button>
        <button type="submit" name="op" value="set-proxy" id="op-set-proxy" hidden></button>
        <button class="pure-button button-secondary button-xsmall" name="op" value="mark-viewed"><i data-feather="eye" ></i>&nbsp;{{ _('Mark viewed') }}</button>
        <button class="pure-button button-secondary button-xsmall" name="op" value="notification-default"><i data-feather="bell" ></i>&nbsp;{{ _('Use default notification') }}</button>
        <button class="pure-button button-secondary button-xsmall" name="op" value="clear-errors"><i data-feather="x-circle" ></i>&nbsp;{{ _('Clear errors') }}</button>
        <button class="pure-button button-secondary button-xsmall" style="background: #dd4242;" name="op" value="clear-history"
                       data-requires-confirm
                       data-confirm-type="danger"
                       data-confirm-title="{{ _('Clear Histories') }}"
                       data-confirm-message="{{ _('<p>Are you sure you want to clear history for the selected items?</p><p>This action cannot be undone.</p>') }}"
                       {# TRANSLATORS: Universally recognized; typically left as-is. dennis-ignore: W302 #}
                       data-confirm-button="{{ _('OK') }}"><i data-feather="trash-2" ></i>&nbsp;{{ _('Clear/reset history') }}</button>
        <button class="pure-button button-secondary button-xsmall" style="background: #dd4242;" name="op" value="delete"
                       data-requires-confirm
                       data-confirm-type="danger"
                       data-confirm-title="{{ _('Delete Watches?') }}"
                       data-confirm-message="{{ _('<p><strong>Are you sure you want to delete the selected watches?</strong></p><p>This action cannot be undone.</p>') }}"
                       data-confirm-button="{{ _('Delete') }}"><i data-feather="trash" ></i>&nbsp;{{ _('Delete') }}</button>
        <button type="button" class="pure-button button-xsmall" id="check-cancel" style="background: var(--color-background-button-cancel); color: #333;"><i data-feather="x" ></i>&nbsp;{{ _('Close') }}</button>
    </div>

        {%- set table_classes = [
            'favicon-enabled' if 'favicons_enabled' not in ui_settings or ui_settings['favicons_enabled'] else 'favicon-not-enabled',
        ] -%}
        <div class="cdio-table-clip">
        <table class="pure-table cdio-table watch-table {{ table_classes | reject('equalto', '') | join(' ') }}">
            <thead>
            <tr>
                {%- set link_order = "desc" if sort_order  == 'asc' else "asc" -%}
                {%- set arrow_span = "" -%}
                <th style="white-space: nowrap; text-align: center;"><input style="vertical-align: middle" type="checkbox" id="check-all" > <a class="{{ 'active '+link_order if sort_attribute == 'date_created' else 'inactive' }}"  href="{{url_for('watchlist.index', sort='date_created', order=link_order, **active_filters)}}"># <span class='arrow {{link_order}}'></span></a></th>
                <th id="mute-pause">
                    <div>
                        <a class="{{ 'active '+link_order if sort_attribute == 'paused' else 'inactive' }}" href="{{url_for('watchlist.index', sort='paused', order=link_order, **active_filters)}}"><i data-feather="pause" style="width: 16px; height: 16px;"></i><span class='arrow {{link_order}}'></span></a>
                        <a class="{{ 'active '+link_order if sort_attribute == 'notification_muted' else 'inactive' }}" href="{{url_for('watchlist.index', sort='notification_muted', order=link_order, **active_filters)}}"><i data-feather="volume-2" style="width: 16px; height: 16px;"></i><span class='arrow {{link_order}}'></span></a>
                    </div>
                </th>
                <th id="th-webpage"><a class="{{ 'active '+link_order if sort_attribute == 'label' else 'inactive' }}" href="{{url_for('watchlist.index', sort='label', order=link_order, **active_filters)}}">{{ _('Web page') }} <span class='arrow {{link_order}}'></span></a></th>
             {%- if any_has_restock_price_processor -%}
                <th>{{ _('Restock & Price') }}</th>
             {%- endif -%}
                <th id="h-lastchecked"><a class="{{ 'active '+link_order if sort_attribute == 'last_checked' else 'inactive' }}" href="{{url_for('watchlist.index', sort='last_checked', order=link_order, **active_filters)}}"><span class="hide-on-mobile">{{ _('Checked') }}</span><span class="hide-on-desktop">{{ _('Checked') }}</span> <span class='arrow {{link_order}}'></span></a></th>
                <th id="h-lastchanged"><a class="{{ 'active '+link_order if sort_attribute == 'last_changed' else 'inactive' }}" href="{{url_for('watchlist.index', sort='last_changed', order=link_order, **active_filters)}}"><span class="hide-on-mobile">{{ _('Changed') }}</span><span class="hide-on-desktop">{{ _('Changed') }}</span> <span class='arrow {{link_order}}'></span></a></th>
                <th class="empty-cell"></th>
            </tr>
            </thead>
            <tbody>
            {%- if not watches|length -%}
            <tr>
                <td colspan="{{ cols_required }}" style="text-wrap: wrap;">{{ _('No web page change detection watches configured, please add a URL in the box above, or') }} <a href="{{ url_for('imports.import_page')}}" >{{ _('import a list') }}</a>.</td>
            </tr>
            {%- endif -%}

            {%- for watch in (watches|sort(attribute=sort_attribute, reverse=sort_order == 'asc'))|pagination_slice(skip=pagination.skip) -%}
                {%- include "watch-overview-single-row.html" -%}
            {%- endfor -%}
            </tbody>
        </table>
        </div>
        {{ pagination.links }}
    </div>
    </form>
</div>
{%- endblock -%}