{{define "title"}}[{{.Playlist.Code}}] {{.Playlist.Name}} - {{.Title}}{{end}}

{{define "metadescription"}}Смотреть бесплатный самообновляемый плейлист {{.Playlist.Name}}, проверить статус, {{.Playlist.Description}}{{end}}

{{define "head"}}
    <style>
        img.tvg-logo{max-width:80px;max-height:80px;padding:2px;border-radius:5px}
        tr.chrow td{padding:3px}
        td.chindex{width:1%}
        td.chlogo{width:100px}
        div.chlist-table{max-height:550px}
        textarea.m3u-raw{font-size:.7rem}
        #qrContainer > img {margin: 0 auto;border: 10px solid white}
    </style>
    <script>
        const DEFAULT_LOGO = 'data:image/png;base64,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'

        function setDefaultLogo(imgtag) {
            imgtag.onerror = null
            imgtag.src = DEFAULT_LOGO
        }

        function showQrCode(code) {
            const url = '{{.BaseUrl}}/' + code;
            const container = document.getElementById('qrContainer');
            container.innerHTML = '';
            new QRCode(container, {
                text: url,
                width: 256,
                height: 256,
                colorDark: '#000000',
                colorLight: '#ffffff',
                correctLevel: QRCode.CorrectLevel.H,
            });
            const modal = new bootstrap.Modal(document.getElementById('qrModal'));
            modal.show();
        }
    </script>
    <script src="/static/js/qrcode.min.js"></script>
{{end}}

{{define "header"}}
    <h2>О плейлисте: {{.Playlist.Name}}</h2>
{{end}}

{{define "content"}}
    {{$pls := .Playlist}}
    <div class="row">
        <div class="col-lg-7">
            <ul class="nav nav-tabs">
                <li class="nav-item small">
                    <a class="nav-link active"
                       type="button"
                       href="#tab-data"
                       data-bs-toggle="tab"
                       data-bs-target="#tab-data"
                    >
                        <span class="mdi mdi-television-classic"></span>&nbsp;Основные&nbsp;данные
                    </a>
                </li>
                {{if .Tabs.Raw.Visible}}
                <li class="nav-item small">
                    <a class="nav-link"
                       type="button"
                       href="#tab-raw"
                       data-bs-toggle="tab"
                       data-bs-target="#tab-raw"
                    >
                        <span class="mdi mdi-text-long"></span>&nbsp;Исходный&nbsp;текст
                    </a>
                </li>
                {{end}}
                {{if .Tabs.Legal.Visible}}
                <li class="nav-item small">
                    <a class="nav-link"
                       type="button"
                       href="#tab-abuse"
                       data-bs-toggle="tab"
                       data-bs-target="#tab-abuse"
                    >
                        <span class="mdi mdi-wallet-outline"></span>&nbsp;Правообладателям
                    </a>
                </li>
                {{end}}
            </ul>
            <div class="tab-content">
                <div class="tab-pane fade show active" id="tab-data" tabindex="0">
                    <table class="table table-dark table-hover small mb-lg-5">
                        <tbody>
                        <tr>
                            <th class="w-25" scope="row">Код</th>
                            <th class="text-break">
                                <span class="pe-3 font-monospace">{{$pls.Code}}</span>
                                {{if not $pls.IsKnown}}
                                    <span class="cursor-help badge small text-dark bg-secondary"
                                          title="Не проверялся"
                                    >unknown</span>
                                {{else if $pls.IsOnline}}
                                    <span class="cursor-help badge small text-dark bg-success"
                                          title="Вероятно, работает"
                                    >online</span>
                                {{else}}
                                    <span class="cursor-help badge small text-dark bg-danger"
                                          title="Вероятно, не работает"
                                    >offline</span>
                                {{end}}
                            </th>
                        </tr>
                        <tr>
                            <th class="w-25" scope="row">Описание</th>
                            <td class="text-break"><p class="mb-0">{{$pls.Description}}</p></td>
                        </tr>
                        <tr>
                            <th class="w-25" scope="row">Короткая ссылка</th>
                            <td>
                                <span onclick="copyPlaylistUrl('{{$pls.Code}}')"
                                      class="cursor-pointer"
                                      title="Нажми на ссылку, чтобы скопировать её в буфер обмена"
                                >
                                    <b class="cursor-pointer font-monospace text-break">{{baseUrl $pls.Code}}</b>
                                    <span class="mdi mdi-content-copy"></span>
                                </span>
                            </td>
                        </tr>
                        <tr>
                            <th class="w-25" scope="row">Источник</th>
                            <td class="text-break">{{$pls.Source}}</td>
                        </tr>
                        <tr>
                            <th class="w-25" scope="row">Наполнение</th>
                            <td class="text-break">
                                {{if and $pls.IsKnown $pls.IsOnline}}
                                    {{if $pls.HasTokens}}
                                        <span class="cursor-help badge bg-info text-dark">
                                            <span class="mdi mdi-paw"></span>
                                        </span>&nbsp;могут быть нестабильные каналы<br>
                                    {{end}}

                                    {{if hasTag $pls.Tags "adult"}}
                                        <span class="cursor-help badge small bg-warning text-dark">18+</span>&nbsp;есть каналы для взрослых<br>
                                    {{end}}

                                    <span class="mdi mdi-folder-open-outline"></span>&nbsp;группы: {{groupCount $pls}}<br>
                                    <span class="mdi mdi-video-outline"></span>&nbsp;каналы:
                                    <span class="cursor-help text-success" title="Возможно, рабочие каналы">
                                        {{$pls.OnlineCount}} ({{$pls.OnlinePercent}}%)
                                    </span>
                                    +
                                    <span class="cursor-help text-danger" title="Возможно, НЕрабочие каналы">
                                        {{$pls.OfflineCount}} ({{$pls.OfflinePercent}}%)
                                    </span>
                                    = {{channelCount $pls}}
                                {{end}}
                            </td>
                        </tr>
                        <tr>
                            <th scope="row">Возможности</th>
                            <td class="text-break">
                                {{if and $pls.IsKnown $pls.IsOnline}}
                                    <span class="mdi mdi-newspaper-variant-outline"></span>&nbsp;Программа передач:&nbsp;{{if $pls.HasTvg}}есть{{else}}нет{{end}}<br>
                                    <span class="mdi mdi-skip-backward"></span>&nbsp;Перемотка&nbsp;(архив):&nbsp;{{if $pls.HasCatchup}}есть{{else}}нет{{end}}
                                {{end}}
                            </td>
                        </tr>
                        <tr class="">
                            <th class="text-secondary w-25" scope="row">M3U</th>
                            <td class="text-secondary text-break">{{$pls.Url}}</td>
                        </tr>
                        <tr class="">
                            <th class="text-secondary w-25" scope="row">Проверка плейлиста</th>
                            <td class="text-secondary text-break">
                                <span title="Фактическая метка времени окончания проверки плейлиста">
                                    {{formatDate $pls.CheckedAt}}
                                </span>
                            </td>
                        </tr>
                        {{if and $pls.IsKnown (not $pls.IsOnline)}}
                            <tr class="text-secondary">
                                <th class="w-25" scope="row">Ошибка проверки</th>
                                <td class="text-break">{{$pls.Content}}</td>
                            </tr>
                        {{end}}
                        </tbody>
                    </table>

                    {{if $pls.Attributes}}
                        <h4>Дополнительные атрибуты</h4>
                        <table class="table table-dark table-hover small font-monospace">
                            <tbody>
                            {{range $attr, $val := $pls.Attributes}}
                                <tr>
                                    <th class="w-25" scope="row">{{$attr}}</th>
                                    <td class="text-break">{{$val}}</td>
                                </tr>
                            {{end}}
                            </tbody>
                        </table>
                    {{end}}
                </div>
                {{if .Tabs.Raw.Visible}}
                <div class="tab-pane fade" id="tab-raw" tabindex="1">
                    <button class="btn btn-sm btn-success my-3"
                            id="saveM3UBtn"
                            onclick="savePlaylist()"
                    >
                        <span class="mdi mdi-download"></span>&nbsp;{{$pls.Code}}.m3u
                    </button>
                    <button type="button"
                            class="btn btn-sm btn-outline-light ms-2"
                            onclick="showQrCode('{{$pls.Code}}')"
                            title="Показать QR-код"
                    >
                        <span class="mdi mdi-qrcode-scan"></span>&nbsp;QR-код
                    </button>
                    <textarea class="form-control bg-dark text-light font-monospace mb-3 mb-md-0 m3u-raw"
                              rows="40"
                              id="m3u-raw"
                              readonly
                    >{{$pls.Content}}</textarea>
                </div>
                {{end}}
                {{if .Tabs.Legal.Visible}}
                <div class="tab-pane fade" id="tab-abuse" tabindex="2">
                    {{if .Tabs.Legal.Text}}
                        {{.Tabs.Legal.Text}}
                    {{else}}
                    <p class="my-3">
                        Данные, представленные на данной странице, получены автоматически из открыто доступных в
                        интернете IPTV-плейлистов, опубликованных третьими лицами.
                        При наличии технической возможности, источник плейлиста может быть указан на вкладке "Основные
                        данные".
                    </p>
                    <p class="my-3">
                        Сервис {{baseUrl ""}} не размещает и не транслирует медиаконтент, не создаёт, не призывает
                        использовать и распространять плейлисты третьих лиц, а также не оказывает услуг по ретрансляции
                        телепрограмм.
                    </p>
                    <p class="my-3">
                        Информация о телеканалах (наименования, логотипы, технический статус и другие сведения)
                        формируется исключительно путём обработки содержимого самого плейлиста.
                        Вся информация носит технический и ознакомительный характер, и её достоверность не гарантируется.
                    </p>
                    <p class="my-3">
                        Все права на торговые марки и графические изображения принадлежат их законным владельцам.
                    </p>
                    {{end}}
                </div>
                {{end}}
            </div>
        </div>

        <div class="col-lg-5">
            <h4>Список каналов:&nbsp;<span id="chcount">{{channelCount $pls}}</span></h4>
            {{if gt (channelCount $pls) 0}}
                {{if gt (groupCount $pls) 1}}
                <div class="row my-3">
                    <div class="col-12">
                        {{if gt (channelCount $pls) 100}}
                            <div class="alert alert-warning small" role="alert" id="chListLoading">
                                <div class="spinner-border text-success spinner-border-sm" role="status"></div>
                                Загрузка...
                            </div>
                        {{end}}
                        <div class="input-group">
                            <select id="groupSelector"
                                    class="form-select form-select-sm border-secondary bg-dark text-light"
                                    onchange="updateFilter()"
                            >
                                <option selected value="all">Все группы</option>
                                {{range $pls.Groups}}
                                <option value="{{.Id}}">{{.Name}}</option>
                                {{end}}
                            </select>

                            <button type="button"
                                    onclick="resetGroup()"
                                    class="btn btn-sm btn-outline-secondary"
                                    title="Сбросить группу"
                            >
                                <span class="mdi mdi-close"></span>
                            </button>
                        </div>
                    </div>
                </div>
                {{end}}
                <div class="row my-3">
                    <div class="col-12">
                        <div class="input-group">
                            <input type="text"
                                   id="search-field"
                                   class="cursor-help form-control form-control-sm border-secondary bg-dark text-light fuzzy-search"
                                   placeholder="Поиск каналов..."
                                   title="Начни вводить название"
                            />

                            <input type="radio"
                                   class="btn-check"
                                   name="chFilter"
                                   id="chfAll"
                                   autocomplete="off"
                                   onclick="updateFilter()"
                                   checked
                            >
                            <label class="btn btn-sm btn-outline-secondary"
                                   for="chfAll"
                                   title="Выбрать все каналы"
                            >
                                <span class="mdi mdi-radiobox-marked"></span>
                            </label>

                            <input type="radio"
                                   class="btn-check"
                                   name="chFilter"
                                   id="chfOnline"
                                   autocomplete="off"
                                   onclick="updateFilter()"
                            >
                            <label class="btn btn-sm btn-outline-success"
                                   for="chfOnline"
                                   title="Выбрать только онлайн каналы"
                            >
                                <span class="mdi mdi-radiobox-marked"></span>{{$pls.OnlineCount}}
                            </label>

                            <input type="radio"
                                   class="btn-check"
                                   name="chFilter"
                                   id="chfOffline"
                                   autocomplete="off"
                                   onclick="updateFilter()"
                            >
                            <label class="btn btn-sm btn-outline-danger"
                                   for="chfOffline"
                                   title="Выбрать только оффлайн каналы"
                            >
                                <span class="mdi mdi-radiobox-marked"></span>{{$pls.OfflineCount}}
                            </label>

                            <button type="button"
                                    class="btn btn-sm btn-outline-secondary"
                                    onclick="resetSearch()"
                                    title="Сбросить фильтрацию"
                            >
                                <span class="mdi mdi-close"></span>
                            </button>
                        </div>

                        <div class="my-3">
                            {{range $pls.Tags}}
                            <input type="checkbox"
                                   class="btn-check"
                                   id="btn-tag-{{.}}"
                                   data-tag="{{.}}"
                                   autocomplete="off"
                                   onclick="updateFilter()"
                            >
                            <label class="badge btn btn-sm btn-outline-secondary rounded-pill"
                                   for="btn-tag-{{.}}"
                                   title="Нажми для фильтрации каналов по тегу, нажми ещё раз чтобы снять фильтр"
                            >#{{.}}</label>
                            {{end}}
                        </div>
                    </div>
                </div>

                <div class="chlist-table overflow-auto">
                    <table id="chlist" class="table table-dark table-hover small">
                        <tbody class="list">
                        </tbody>
                    </table>
                </div>
            {{else if and $pls.IsKnown (not $pls.IsOnline)}}
                <div class="alert alert-danger small" role="alert">
                    Ошибка плейлиста: {{$pls.Content}}
                </div>
            {{else if not $pls.IsKnown}}
                <div class="alert alert-warning small" role="alert" id="chListLoading">
                    Список каналов сейчас неизвестен: плейлист ещё не проверялся, либо данные о последней проверке потеряли актуальность.
                    <br><br>
                    Вернитесь на эту страницу позже. Каналы будут известны, когда плейлист будет в статусе online.
                </div>
            {{end}}
        </div>
    </div>
{{end}}

{{define "footer"}}
    <div class="modal fade" id="qrModal" tabindex="-1" aria-hidden="true">
        <div class="modal-dialog modal-dialog-centered">
            <div class="modal-content bg-dark text-light border-secondary">
                <div class="modal-header border-secondary">
                    <h5 class="modal-title">QR-код плейлиста</h5>
                    <button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body text-center">
                    <div id="qrContainer"></div>
                </div>
            </div>
        </div>
    </div>

    {{if and .Playlist.IsKnown .Playlist.IsOnline}}
    <script src="https://cdn.jsdelivr.net/npm/list.js@2.3.1/dist/list.min.js"></script>

    <script>
        function getChannelTemplate(channel) {
            const httpCode = channel.status ?? '(неизвестно)'
            const errText = !!channel.error
                ? channel.error.replace(/&/g, '&amp;')
                    .replace(/</g, '&lt;')
                    .replace(/>/g, '&gt;')
                    .replace(/"/g, '&quot;')
                    .replace(/'/g, '&#39;')
                : '(нет)'

            const logoUrl = channel.attributes['tvg-logo'] ?? DEFAULT_LOGO
            const logoHint = !!channel.attributes['tvg-logo']
                ? `Логотип канала '${channel.title}'`
                : `Нет логотипа для канала '${channel.title}'`

            const statusIconColor = channel.isOnline ? 'text-success' : 'text-danger'
            const statusIconHint = channel.isOnline
                ? 'Состояние: онлайн (возможно, работает прямо сейчас)"'
                : 'Состояние: оффлайн (не работал в момент проверки или ошибка проверки)"'

            const adultIcon = channel.tags.indexOf('adult') !== -1
                ? '<span class="badge small bg-warning text-dark" title="Канал для взрослых!">18+</span>'
                : ''

            const pawIcon = channel.hasToken
                ? '<span class="cursor-help badge small bg-info text-dark" title="Может быть нестабилен"><span class="mdi mdi-paw"></span></span>'
                : ''

            const tvgId = !!channel.attributes['tvg-id']
                ? `<div title="Идентификатор канала для телепрограммы (tvg-id)" class="cursor-help"><span class="mdi mdi-star-outline me-1"></span>&nbsp;${channel.attributes['tvg-id']}</div>`
                : ``

            const mimeType = !!channel.contentType
                ? `<div title="Тип контента (mime-type)" class="cursor-help"><span class="mdi mdi-eye-outline me-1"></span>&nbsp;${channel.contentType}</div>`
                : ``

            const tags = channel.tags.length > 0
                ? `<span class="mdi mdi-tag-outline cursor-help me-1" title="Теги"></span>&nbsp;`
                    + channel.tags.map((tag) => `<span class="chtag">#${tag}</span>`).join(' ')
                : ``

            return `<tr class="chrow" title="&#010;HTTP: ${httpCode}&#010;Error: ${errText}">
                <td class="chlogo text-center">
                    <img class="tvg-logo" alt="${logoHint}" title="${logoHint}" src="${logoUrl}" onerror="setDefaultLogo(this)" />
                </td>
                <td class="text-break">
                    <span class="mdi mdi-radiobox-marked cursor-help me-1 ${statusIconColor}" title="${statusIconHint}"></span>
                    ${adultIcon}
                    ${pawIcon}
                    ${channel.title}
                    <div class="text-secondary small">
                        ${tvgId}
                        ${mimeType}
                        ${tags}
                    </div>
                </td>
            </tr>`
        }

        const options = {
            searchColumns: ['title'],
            item: (channel) => getChannelTemplate(channel),
        };
        const values = {{jsonChannels .Playlist.ViewChannels}}

        const list = new List('chlist', options, values)
        list.on('updated', (data) => document.getElementById('chcount').innerText = data.visibleItems.length)
        document.getElementById('search-field').addEventListener('keyup', (e) => list.search(e.target.value))

        document.addEventListener("DOMContentLoaded", () => {
            const alert = document.getElementById("chListLoading")
            !!alert && alert.remove()
        });

        function savePlaylist() {
            const link = document.createElement("a");
            const content = document.getElementById("m3u-raw").value
            const file = new Blob([content], { type: 'text/plain' });
            link.href = URL.createObjectURL(file);
            link.download = "{{.Playlist.Code}}.m3u";
            link.click();
            URL.revokeObjectURL(link.href);
        }

        function resetGroup() {
            document.getElementById('groupSelector').value = 'all'
            updateFilter()
        }

        function resetSearch() {
            list.search('')
            document.getElementById('search-field').value = ''
            document.getElementById('chfAll').checked = true
            document.querySelectorAll('input[id*="btn-tag-"]:checked').forEach(tag => tag.checked = false)
            updateFilter()
        }

        function updateFilter() {
            const selectedGroupId = document.getElementById('groupSelector')?.value ?? 'all';
            const tagsElements = document.querySelectorAll('input[id*="btn-tag-"]:checked')
            const tagsSelected = []
            tagsElements.forEach(tag => tagsSelected.push(tag.attributes['data-tag'].value));
            const activeType = document.querySelector('input[name="chFilter"]:checked').id;
            switch (activeType) {
                case 'chfAll':
                    list.filter(item => {
                        const chTags = item.values().tags
                        const isGroupValid = item.values().groupId === selectedGroupId || selectedGroupId === 'all';
                        const tagsIntersection = tagsSelected.filter(tagSelected => chTags.includes(tagSelected));
                        const hasValidTags = tagsIntersection.length > 0 || tagsSelected.length === 0;
                        return isGroupValid && hasValidTags;
                    })
                    break

                case 'chfOnline':
                    list.filter(item => {
                        const isOnline = item.values().isOnline
                        const chTags = item.values().tags
                        const isGroupValid = item.values().groupId === selectedGroupId || selectedGroupId === 'all';
                        const tagsIntersection = tagsSelected.filter(tagSelected => chTags.includes(tagSelected));
                        const hasValidTags = tagsIntersection.length > 0 || tagsSelected.length === 0;
                        return isGroupValid && isOnline && hasValidTags
                    })
                    break

                case 'chfOffline':
                    list.filter(item => {
                        const isOffline = !item.values().isOnline
                        const chTags = item.values().tags
                        const isGroupValid = item.values().groupId === selectedGroupId || selectedGroupId === 'all';
                        const tagsIntersection = tagsSelected.filter(tagSelected => chTags.includes(tagSelected));
                        const hasValidTags = tagsIntersection.length > 0 || tagsSelected.length === 0;
                        return isGroupValid && isOffline && hasValidTags
                    })
                    break
            }
        }
    </script>
    {{end}}
{{end}}
