Control Emotes Panel 2.6.51 (C) tapeavion

Twitch emoji blocking in Chat with a management interface and context menu .

As of 22.04.2025. See апошняя версія.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name          Control Emotes Panel 2.6.51 (C) tapeavion
// @version       2.6.51
// @description   Twitch emoji blocking in Chat with a management interface and context menu .
// @author        Gullampis810
// @license       MIT
// @match        https://www.twitch.tv/*
// @match         https://blank.org/*
// @grant         GM_registerMenuCommand
// @grant         GM_unregisterMenuCommand
// @grant         GM_setValue
// @grant         GM_getValue
// @icon          https://raw.githubusercontent.com/sopernik566/icons/refs/heads/main/7BTVEmotesPanel256.ico
// @namespace     http://tampermonkey.net/
// @tag          twitch
// @tag          emote-blocker
// @tag          chat-filter
// @tag          block-emotes
// @tag          twitch-chat
// @tag          7tv
// @tag          bttv
// @tag          ffz
// @tag          twitch-channel
// @tag          block-all-emotes
// @tag          Emote-Blocker-Twitch-in-chat
// ==/UserScript==


(function () {
    'use strict';

    // Подключаем Chart.js через CDN
const chartJsScript = document.createElement('script');
chartJsScript.src = 'https://cdn.jsdelivr.net/npm/chart.js';
chartJsScript.async = true;
document.head.appendChild(chartJsScript);


    // === объект для хранения текущих стилей кнопки DeleteButton в случае пересоздания и сброса стиля //
    let currentDeleteButtonStyles = {
        background: 'rgb(168, 77, 77)', // Начальный цвет из hoverStyle
        color: '#fff',
        hoverBackground: 'linear-gradient(135deg, #f75557 0%, #480a0c 56%, #4e1314 98%, #ff4d4d 100%)'
    };

    let blockedEmotes = [];
    let blockedChannels = [];

        // глобальное определение для поисковой строки
    function debounce(func, wait) {
        let timeout;
        return function (...args) {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), wait);
        };
    }

    // Функция для безопасного получения и парсинга данных
    function loadData(key, defaultValue) {
        const rawData = GM_getValue(key, defaultValue);
        try {
            return typeof rawData === 'string' ? JSON.parse(rawData) : rawData;
        } catch (e) {
            console.error(`Ошибка при парсинге ${key}:`, e);
            return defaultValue; // Возвращаем значение по умолчанию в случае ошибки
        }
    }

    // Загружаем данные при старте
    blockedEmotes = loadData("blockedEmotes", []);
    blockedChannels = loadData("blockedChannels", []);
    console.log("[7BTV Control Emotes Panel] Загружены blockedEmotes:", blockedEmotes);
    console.log("[7BTV Control Emotes Panel] Загружены blockedChannels:", blockedChannels);

    let isPanelOpen = GM_getValue('isPanelOpen', false);



//=== Функция для перемещения панели ===//
function makePanelDraggable(panel) {
    let offsetX = 0, offsetY = 0, isDragging = false;

    // Создаем заголовок, за который можно перетаскивать
    const dragHandle = document.createElement('div');
    dragHandle.style.width = '100%';
    dragHandle.style.height = '656px';
    dragHandle.style.background = 'rgba(0, 0, 0, 0.0)';
    dragHandle.style.cursor = 'grab';
    dragHandle.style.position = 'absolute';
    dragHandle.style.top = '0';
    dragHandle.style.left = '0';
    dragHandle.style.zIndex = '-1';
    dragHandle.style.borderRadius = '8px 8px 0 0';
    panel.appendChild(dragHandle);

    // Начало перемещения
    dragHandle.addEventListener('mousedown', (e) => {
        isDragging = true;
        offsetX = e.clientX - panel.getBoundingClientRect().left;
        offsetY = e.clientY - panel.getBoundingClientRect().top;
        dragHandle.style.cursor = 'grabbing';
    });

    // Перемещение панели
    document.addEventListener('mousemove', (e) => {
        if (!isDragging) return;
        panel.style.left = `${e.clientX - offsetX}px`;
        panel.style.top = `${e.clientY - offsetY}px`;
    });

    // Остановка перемещения
    document.addEventListener('mouseup', () => {
        isDragging = false;
        dragHandle.style.cursor = 'grab';
    });
}

//===================================== Панель управления =======================================//
    const controlPanel = document.createElement('div');
    controlPanel.style.position = 'fixed'; // Фиксируем панель на экране
    controlPanel.style.bottom = '124px'; // Располагаем панель на 124px от нижней границы экрана
    controlPanel.style.right = '380px'; // Располагаем панель на 310px от правой границы экрана
    controlPanel.style.width = '690px'; // Ширина панели
    controlPanel.style.height = '656px'; // Высота панели
    controlPanel.style.backgroundColor = '#5c5065'; // Цвет фона панели
    controlPanel.style.background = '-webkit-linear-gradient(270deg, hsla(50, 76%, 56%, 1) 0%, hsla(32, 83%, 49%, 1) 25%, hsla(0, 37%, 37%, 1) 59%, hsla(276, 47%,         24%, 1) 79%, hsla(261, 11%, 53%, 1) 100%)'; // Применяем градиентный фон

    controlPanel.style.border = '1px solid #ccc'; // Цвет и стиль границы панели
    controlPanel.style.borderRadius = '8px'; // Скругляем углы панели
    controlPanel.style.padding = '10px'; // Отступы внутри панели
    controlPanel.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)'; // Добавляем тень панели
    controlPanel.style.zIndex = 10000; // Устанавливаем высокий z-index, чтобы панель была поверх других элементов
    controlPanel.style.fontFamily = 'Arial, sans-serif'; // Шрифт текста на панели
    controlPanel.style.transition = 'height 0.3s ease'; // Плавное изменение высоты при изменении
    controlPanel.style.overflow = 'hidden'; // Скрытие содержимого, если оно выходит за пределы панели


        // Метка версии внизу панели
const versionLabel = document.createElement('div');
versionLabel.innerText = 'v.2.6.51';
versionLabel.style.position = 'absolute';
versionLabel.style.top = '4px';
versionLabel.style.right = '640px';
versionLabel.style.color = 'rgb(62, 33, 85)';
versionLabel.style.fontSize = '12px';
versionLabel.style.fontFamily = 'Arial, sans-serif';
versionLabel.style.fontWeight = 'bold';
controlPanel.appendChild(versionLabel);


// Добавляем панель в DOM и активируем перетаскивание
document.body.appendChild(controlPanel);
makePanelDraggable(controlPanel);



//---------------Текст с  Названием листа список list of BlockedEmotes ------------------------//
const title = document.createElement('h4');
title.innerText = 'list of BlockedEmotes';
title.style.margin = '-5px 0px 10px'; // Обновленный стиль margin
title.style.color = ' #2a1e38'; // Обновленный цвет
title.style.position = 'relative'; // Устанавливаем позицию относительно
title.style.bottom = '55px'; // Сдвиг по вертикали
controlPanel.appendChild(title);



//--------------- Список заблокированных каналов ------------------//
const list = document.createElement('ul');
list.id = 'blockedList';
list.style.position = 'relative';
list.style.bottom = '34px';
list.style.border = '1px solid #ffffff'; // Белая граница
list.style.borderRadius = '0px 0px 8px 8px'; // Скругление углов
list.style.boxShadow = ' rgb(0 0 0 / 67%) -18px 69px 40px 0 inset '; // Вставка тени в контейнер
list.style.listStyle = 'none'; // Убираем стандартные маркеры списка
list.style.padding = '0'; // Убираем отступы
list.style.margin = '-14px 0px 10px'; // Отступ снизу
list.style.maxHeight = '570px'; // Устанавливаем максимальную высоту
list.style.height = '410px'; // Высота списка
list.style.overflowY = 'auto'; // Включаем вертикальную прокрутку


//==================================== ГРАДИЕНТ ФОН СПИСОК =================================================//
// Добавляем линейный градиент фона с кроссбраузерностью
list.style.background = 'linear-gradient(45deg, hsla(292, 44%, 16%, 1) 0%, hsla(173, 29%, 48%, 1) 100%)';
list.style.background = '-moz-linear-gradient(45deg, hsla(292, 44%, 16%, 1) 0%, hsla(173, 29%, 48%, 1) 100%)'; // Для Firefox
list.style.background = '-webkit-linear-gradient(45deg, hsla(292, 44%, 16%, 1) 0%, hsla(173, 29%, 48%, 1) 100%)'; // Для Safari и Chrome
list.style.filter = 'progid: DXImageTransform.Microsoft.gradient(startColorstr="#36173b", endColorstr="#589F97", GradientType=1)'; // Для старых версий IE
list.style.color = '#fff'; // Белый цвет текста

//==========  кастомный scroll bar для списка =============//
const style = document.createElement('style');
style.innerHTML = `
#blockedList::-webkit-scrollbar {
  width: 25px; /* Ширина скроллбара */
}

#blockedList::-webkit-scrollbar-thumb {
  background-color: #C1A5EF; /* Цвет бегунка */
  border-radius: 8px; /* Скругление бегунка */
  border: 3px solid #4F3E6A; /* Внутренний отступ (цвет трека) */
  height: 80px; /* Высота бегунка */
}

#blockedList::-webkit-scrollbar-thumb:hover {
  background-color: #C6AEFF; /* Цвет бегунка при наведении */
}

#blockedList::-webkit-scrollbar-thumb:active {
  background-color: #B097C9; /* Цвет бегунка при активном состоянии */
}

#blockedList::-webkit-scrollbar-track {
  background: #455565; /* Цвет трека */
  border-radius: 0px 0px 8px 0px; /* Скругление только нижнего правого угла */
}

#blockedList::-webkit-scrollbar-track:hover {
  background-color: #455565; /* Цвет трека при наведении */
}

#blockedList::-webkit-scrollbar-track:active {
  background-color: #455565; /* Цвет трека при активном состоянии */
}

`;
document.head.appendChild(style);

// hover blocked-item элемент списка //
const hoverStyle = document.createElement('style');
hoverStyle.innerHTML = `
    .blocked-item {
        transition: background-color 0.3s ease, color 0.3s ease;
    }
    .blocked-item:hover {
        background-color: rgba(167, 54, 54, 0.52);
        color: #42d13a;
    }
    .blocked-item:hover span {
        color: #42d13a;
    }
    .new-item {
        background-color:#28a828;
        transition: background-color 0.3s ease;
    }
    .new-item:hover {
        background-color: #3a2252;
        color: #af7fcf;
    }
    .new-item:hover span {
        color: #af7fcf;
    }
    #sortContainer button {
        background: none;
        border: none;
        color: inherit;
        font-family: inherit;
        font-size: inherit;
        padding: 0 10px;
        transition: color 0.3s ease;
    }
    #sortContainer button:hover {
        color: #9ae048;
    }
`;
document.head.appendChild(hoverStyle);



const highlightStyle = document.createElement('style');
highlightStyle.innerHTML = `
    .blocked-item .highlight {
        background-color: #FFEB3B  !important; /* Красный фон для подсветки */
        color:rgb(0, 0, 0) !important; /* Белый текст для контраста */
        padding: 0 2px !important;
        border-radius: 2px !important;
        transition: background-color 0.5s ease !important;
    }
    .blocked-item.highlight-item {
        background-color: rgba(163, 161, 18, 0.83) !important; /* Полупрозрачная красная подсветка для всего элемента */
        transition: background-color 0.5s ease !important;
    }
     .last-item-highlight {
          background-color: #279479; /* Полупрозрачный золотой фон */
          transition: background-color 0.5s ease; /* Плавное исчезновение */
}
`;
document.head.appendChild(highlightStyle);

document.head.appendChild(style);

const buttonColor = ' #907cad'; // Общий цвет для кнопок
const buttonShadow = '0 4px 8px rgba(0, 0, 0, 0.6)'; // Тень для кнопок (60% прозрачности)



// Функция для обновления списка заблокированных каналов

// Переменные для хранения ID заблокированных элементов
let blockedEmoteIDs = new Set();
let blockedChannelIDs = new Set();
let newlyAddedIds = new Set();

function updateBlockedList() {
    list.innerHTML = '';

    // Очистка и обновление Set для быстрого поиска ID
    blockedEmoteIDs.clear();
    blockedChannelIDs.clear();

    function createListItem(channel, isNew = false) {
        const item = document.createElement('li');
        item.className = 'blocked-item';
        item.dataset.id = channel.id;

        if (isNew) {
            item.classList.add('new-item');
            setTimeout(() => {
                item.classList.remove('new-item');
            }, 1800000);
        }

        item.style.display = 'flex';
        item.style.flexDirection = 'column';
        item.style.padding = '5px';
        item.style.borderBottom = '1px solid #eee';

        const topRow = document.createElement('div');
        topRow.style.display = 'flex';
        topRow.style.justifyContent = 'space-between';
        topRow.style.alignItems = 'center';

        const channelName = document.createElement('span');
        if (channel.platform === 'TwitchChannel') {
            channelName.innerText = `${channel.platform} > name emote: ${channel.emoteName}`;
        } else {
            channelName.innerText = `${channel.platform} > ${channel.emoteName}`;
        }
        channelName.classList.add('list-item-text');
        channelName.style.flex = '1';
        channelName.style.fontSize = '14px';
        channelName.style.fontWeight = 'bold';
        channelName.style.whiteSpace = 'nowrap';
        channelName.style.overflow = 'hidden';
        channelName.style.textOverflow = 'ellipsis';
        topRow.appendChild(channelName);

        const dateInfo = document.createElement('span');
        const date = new Date(channel.date);
        dateInfo.innerText = isNaN(date.getTime())
            ? 'Unknown Date'
            : date.toLocaleString('en-GB', { day: '2-digit', month: '2-digit', year: 'numeric', hour: '2-digit', minute: '2-digit' });
        dateInfo.classList.add('list-item-date');
        dateInfo.style.marginRight = '30px';
        dateInfo.style.fontSize = '14px';
        topRow.appendChild(dateInfo);

        const removeButton = document.createElement('button');
        removeButton.innerText = 'Delete';
        removeButton.classList.add('delete-button');
        console.log("[7BTV Control Emotes Panel] Создана кнопка Delete для элемента:", channel.id);

        // Используем сохранённые стили из currentDeleteButtonStyles
        removeButton.style.background = currentDeleteButtonStyles.background;
        removeButton.style.color = currentDeleteButtonStyles.color;
        removeButton.style.height = '35px';
        removeButton.style.width = '75px';
        removeButton.style.fontWeight = 'bold';
        removeButton.style.fontSize = '16px';
        removeButton.style.border = 'none';
        removeButton.style.borderRadius = '4px';
        removeButton.style.cursor = 'pointer';
        removeButton.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.6)';
        removeButton.style.display = 'flex';
        removeButton.style.alignItems = 'center';
        removeButton.style.justifyContent = 'center';
        removeButton.style.transition = 'background 0.3s ease';
        removeButton.style.opacity = '1';
        removeButton.style.visibility = 'visible';

        // Добавляем обработчики наведения
        removeButton.onmouseover = () => {
            removeButton.style.background = currentDeleteButtonStyles.hoverBackground;
        };
        removeButton.onmouseout = () => {
            removeButton.style.background = currentDeleteButtonStyles.background;
        };

        removeButton.onclick = function () {
            if (channel.platform === 'TwitchChannel') {
                blockedChannels = blockedChannels.filter(c => c.id !== channel.id);
                blockedChannelIDs.delete(channel.id);
                GM_setValue("blockedChannels", JSON.stringify(blockedChannels, null, 2));
            } else {
                blockedEmotes = blockedEmotes.filter(c => c.id !== channel.id);
                blockedEmoteIDs.delete(channel.id);
                GM_setValue("blockedEmotes", JSON.stringify(blockedEmotes, null, 2));
            }

            newlyAddedIds.delete(channel.id);
            updateBlockedList();
            updateCounter();
            showEmoteForChannel(channel);
        };

        topRow.appendChild(removeButton);
        item.appendChild(topRow);

        const channelLink = document.createElement('span');
        channelLink.innerText = `(prefix: ${channel.name})`;
        channelLink.classList.add('list-item-link');
        channelLink.style.fontSize = '14px';
        channelLink.style.wordBreak = 'break-word';
        channelLink.style.marginTop = '1px';
        item.appendChild(channelLink);

        return item;
    }

    // Заполняем списки и обновляем Set
    blockedChannels.forEach(channel => {
        blockedChannelIDs.add(channel.id);
        const isNew = newlyAddedIds.has(channel.id) && Array.from(newlyAddedIds).pop() === channel.id;
        list.appendChild(createListItem(channel, isNew));
    });

    blockedEmotes.forEach(channel => {
        blockedEmoteIDs.add(channel.id);
        const isNew = newlyAddedIds.has(channel.id) && Array.from(newlyAddedIds).pop() === channel.id;
        list.appendChild(createListItem(channel, isNew));
    });

    // Прокручиваем к последнему добавленному элементу внутри контейнера list
    if (newlyAddedIds.size > 0) {
        const lastAddedId = Array.from(newlyAddedIds).pop();
        const newItem = list.querySelector(`[data-id="${lastAddedId}"]`);
        if (newItem) {
            // Вычисляем позицию нового элемента относительно контейнера list
            const itemOffsetTop = newItem.offsetTop; // Позиция элемента относительно начала списка
            const listHeight = list.clientHeight; // Видимая высота контейнера list
            const itemHeight = newItem.clientHeight; // Высота самого элемента

            // Вычисляем, куда нужно прокрутить, чтобы элемент оказался вверху видимой области
            const scrollPosition = itemOffsetTop - (listHeight / 2) + (itemHeight / 2);

            // Плавно прокручиваем list к нужной позиции
            list.scrollTo({
                top: scrollPosition,
                behavior: 'smooth'
            });
        }
    }

    // Очищаем список новых ID после отображения
    newlyAddedIds.clear();
}

// Добавляем список в панель управления
controlPanel.appendChild(list);




// Создаём контейнер для поисковой строки
const searchContainer = document.createElement('div');
searchContainer.style.display = 'flex';
searchContainer.style.gap = '5px';
searchContainer.style.top = '500px';
searchContainer.style.position = 'relative';

// Создаём поисковую строку
const searchInput = document.createElement('input');
searchInput.type = 'text';
searchInput.placeholder = 'Search in blocked list...';
searchInput.style.background = ' #192427';
searchInput.style.width = '459px';
searchInput.style.left = '132px';
searchInput.style.color = ' #b69dcf';
searchInput.style.fontWeight = 'bold';
searchInput.style.height = '35px';
searchInput.style.padding = '5px';
searchInput.style.border = '1px solid #b69dcf';
searchInput.style.borderRadius = '4px';
searchInput.style.boxShadow = ' #4c2a5e 0px 4px 6px inset';
searchInput.style.position = 'relative';
searchInput.style.bottom = '50px';

// Создаём кнопку поиска
const searchButton = document.createElement('button');
searchButton.innerText = 'Search'; // Меняем текст на "Search"
searchButton.style.background = buttonColor;
searchButton.style.position = 'relative';
searchButton.style.bottom = '50px';
searchButton.style.color = '#fff';
searchButton.style.border = 'none';
searchButton.style.width = '72px';
 searchButton.style.left = '132px';
searchButton.style.borderRadius = '4px';
searchButton.style.padding = '5px 10px';
searchButton.style.cursor = 'pointer';
searchButton.style.fontSize = '16px';
searchButton.style.fontWeight = 'bold';
searchButton.style.boxShadow = buttonShadow;

// Добавляем ховер-эффекты для кнопки поиска
searchButton.onmouseover = function() {
    searchButton.style.background = '-webkit-linear-gradient(135deg, #443157 0%,rgb(90, 69, 122) 56%, #443157 98%, #443157 100%)';
};
searchButton.onmouseout = function() {
    searchButton.style.background = buttonColor;
};

// Обработчик кнопки поиска
searchButton.onclick = () => {
    const searchTerm = searchInput.value.trim();
    filterBlockedList(searchTerm); // Запускаем фильтрацию
};

function filterBlockedList(searchTerm) {
    const lowerSearchTerm = searchTerm.toLowerCase().trim();
    console.log("[7BTV Control Emotes Panel] Поисковый запрос (lowerSearchTerm):", lowerSearchTerm);

    let filteredList = [];

    // Фильтрация списка
    if (!lowerSearchTerm) {
        filteredList = [...blockedChannels, ...blockedEmotes];
        console.log("[7BTV Control Emotes Panel] Поиск пустой, отображаем все элементы:", filteredList);
    } else {
        filteredList = [...blockedChannels, ...blockedEmotes].filter(item => {
            const emoteName = item.emoteName || '';
            const platform = item.platform || '';
            const name = item.name || '';
            const matches =
                emoteName.toLowerCase().includes(lowerSearchTerm) ||
                platform.toLowerCase().includes(lowerSearchTerm) ||
                name.toLowerCase().includes(lowerSearchTerm);
            console.log(`[7BTV Control Emotes Panel] Проверяем элемент: ${JSON.stringify(item)}, совпадение: ${matches}`);
            return matches;
        });
        console.log("[7BTV Control Emotes Panel] Результаты фильтрации:", filteredList);
    }

    // Сохраняем текущую позицию скролла
    const currentScrollPosition = list.scrollTop;
    console.log("[7BTV Control Emotes Panel] Текущая позиция скролла перед обновлением:", currentScrollPosition);

    // Получаем текущие элементы в DOM
    const currentItems = list.querySelectorAll('.blocked-item');
    const existingIds = new Set([...currentItems].map(item => item.dataset.id));

    // Удаляем элементы, которые не прошли фильтрацию
    currentItems.forEach(item => {
        const itemId = item.dataset.id;
        if (!filteredList.some(f => f.id === itemId)) {
            item.remove();
        }
    });

    // Добавляем или обновляем элементы
    filteredList.forEach(channel => {
        const itemId = channel.id;
        let item = list.querySelector(`[data-id="${itemId}"]`);

        if (!item) {
            // Если элемента нет, создаём новый
            item = createListItem(channel);
            list.appendChild(item);
        }

        // Применяем подсветку, если есть поисковый запрос
        if (lowerSearchTerm) {
            const spans = item.querySelectorAll('span');
            spans.forEach(span => {
                const originalText = span.textContent || '';
                if (originalText.toLowerCase().includes(lowerSearchTerm)) {
                    const regex = new RegExp(`(${lowerSearchTerm})`, 'gi');
                    const highlightedText = originalText.replace(regex, '<span class="highlight">$1</span>');
                    span.innerHTML = highlightedText;
                }
            });
        }
    });

    // Прокрутка к первому элементу
    if (filteredList.length > 0) {
        const firstItem = list.querySelector('.blocked-item');
        if (firstItem) {
            console.log("[7BTV Control Emotes Panel] Найден первый элемент для прокрутки:", firstItem);
            const firstItemOffset = firstItem.offsetTop;
            list.scrollTop = firstItemOffset - (list.clientHeight / 2) + (firstItem.clientHeight / 2);
            console.log("[7BTV Control Emotes Panel] Установлен scrollTop:", list.scrollTop);
        } else {
            console.log("[7BTV Control Emotes Panel] Первый элемент не найден в DOM!");
        }
    } else {
        // Если список пуст, восстанавливаем скролл
        console.log("[7BTV Control Emotes Panel] Список пуст, восстанавливаем скролл на:", currentScrollPosition);
        list.scrollTop = currentScrollPosition;
    }

    updateCounter();
}

// Добавляем элементы в контейнер поиска
searchContainer.appendChild(searchInput);
searchContainer.appendChild(searchButton); //   searchButton


// Добавляем контейнер поиска в панель управления
controlPanel.appendChild(searchContainer);

// Далее продолжаем с добавлением списка
controlPanel.appendChild(list);


//================= Функционал для добавления нового канала в список заблокированных ==================//
const inputContainer = document.createElement('div');
inputContainer.style.display = 'flex';
inputContainer.style.gap = '5px';

const input = document.createElement('input');
input.type = 'text';
input.placeholder = 'type to add channel ';
input.style.position = 'relative';
input.style.background = ' #192427';
input.style.color = ' #b69dcf';
input.style.flex = '1';
input.style.fontWeight = 'bold'; // Жирный текст
input.style.height = '35px'; // Отступ между кнопкой и поисковой строкой
input.style.padding = '5px';
input.style.border = '1px solid #b69dcf';
input.style.borderRadius = '4px';
input.style.top = '15px'; // Отступ между кнопкой и поисковой строкой
// Добавление тени с фиолетовым цветом (35% прозрачности) внутрь
input.style.boxShadow = ' #4c2a5e 0px 4px 6px inset'; // Тень фиолетового цвета внутри

//================== Add it Button =====================//
// ==================== Кнопка добавления ===================== //
const addButton = document.createElement('button');
addButton.innerText = 'Add it';
addButton.style.background = buttonColor;
addButton.style.top = '15px'; // Отступ между кнопкой и поисковой строкой
addButton.style.position = 'relative';
addButton.style.color = '#fff';
addButton.style.border = 'none';
addButton.style.width = '72px';
addButton.style.borderRadius = '4px';
addButton.style.padding = '5px 10px';
addButton.style.cursor = 'pointer';
addButton.style.boxShadow = buttonShadow; // Тень для кнопки "Add it"

// Увеличиваем размер текста и делаем его жирным
addButton.style.fontSize = '16px'; // Увеличиваем размер текста
addButton.style.fontWeight = 'bold'; // Жирный текст

// Генерация уникального ID
function generateID() {
    return `emote_${Date.now()}`; // Генерация ID на основе времени
}

addButton.onclick = (event) => {
    event.preventDefault();
    const channel = input.value.trim();
    const platform = platformSelect.value;

    if (channel) {
        let emoteName = channel;
        let emoteUrl = channel;
        const emoteId = generateRandomID();

        // Проверка на дублирование
        const isDuplicate = platform === 'TwitchChannel'
            ? blockedChannels.some(e => e.name === channel && e.platform === platform)
            : blockedEmotes.some(e => e.emoteUrl === channel && e.platform === platform);

        if (isDuplicate) {
            console.log(`%c[7BTV Control Emotes Panel] %cChannel/Emote already blocked: ${channel}`,
                'color: rgb(255, 165, 0); font-weight: bold;',
                'color: rgb(255, 165, 0);');
            return;
        }

        if (platform === '7tv' || platform === 'bttTV' || platform === 'ffz') {
            const img = document.querySelector(`img[src="${channel}"]`);
            if (img) {
                emoteName = img.alt || channel.split('/').pop();
                emoteUrl = img.src || channel;
            }

            const newEmote = {
                id: emoteId,
                name: emoteUrl,
                platform: platform,
                emoteName: emoteName,
                emoteUrl: emoteUrl,
                date: new Date().toISOString()
            };

            blockedEmotes.push(newEmote);
            blockedEmoteIDs.add(emoteId);
            newlyAddedIds.add(emoteId);
            GM_setValue("blockedEmotes", JSON.stringify(blockedEmotes, null, 2));
            console.log(`%c[7BTV Control Emotes Panel] %cAdded to blockedEmotes:`,
                'color: rgb(0, 255, 0); font-weight: bold;',
                'color: rgb(0, 255, 0);', newEmote);
        } else if (platform === 'TwitchChannel') {
            const prefix = channel.split(/[^a-zA-Z0-9]/)[0];
            emoteUrl = prefix;

            const newChannel = {
                id: emoteId,
                name: emoteUrl,
                platform: platform,
                emoteName: emoteName,
                emoteUrl: emoteUrl,
                date: new Date().toISOString()
            };

            blockedChannels.push(newChannel);
            blockedChannelIDs.add(emoteId);
            newlyAddedIds.add(emoteId);
            GM_setValue("blockedChannels", JSON.stringify(blockedChannels, null, 2));
            console.log(`%c[7BTV Control Emotes Panel] %cAdded to blockedChannels:`,
                'color: rgb(0, 255, 0); font-weight: bold;',
                'color: rgb(0, 255, 0);', newChannel);
        }

        const chatContainer = document.querySelector('.chat-scrollable-area__message-container');
        if (chatContainer) {
            toggleEmotesInNode(chatContainer);
        }

        updateBlockedList();
        updateCounter();
        input.value = '';
    }
};



// ==================== Создание выпадающего списка платформ ===================== //
const platformSelect = document.createElement('select');
platformSelect.style.top = '15px'; // Отступ между кнопкой и поисковой строкой
platformSelect.style.position = 'relative';
platformSelect.style.height = '35px'; // Высота выпадающего списка
platformSelect.style.border = '1px solid #c1a5ef';
platformSelect.style.background = '#192427';
platformSelect.style.borderRadius = '4px';
platformSelect.style.padding = '5px';
platformSelect.style.fontWeight = 'bold'; // Жирный текст
platformSelect.style.color = ' #b69dcf';

const platforms = ['TwitchChannel', '7tv', 'bttTV', 'ffz'];
platforms.forEach(platform => {
    const option = document.createElement('option');
    option.value = platform;
    option.innerText = platform;
    platformSelect.appendChild(option);
});

// ==================== Подсказки для выбора платформы ===================== //
platformSelect.addEventListener('change', () => {
    const placeholderText = {
        'TwitchChannel': 'example prefix abcd123',
        '7tv': 'link example: https://cdn.7tv.app/emote/00000000000000000000000000/2x.webp',
        'bttTV': 'link example: https://cdn.betterttv.net/emote/000000000000000000000000/2x.webp',
        'ffz': 'link example: https://cdn.frankerfacez.com/emote/0000/2'
    };
    input.placeholder = placeholderText[platformSelect.value];
});

// ==================== Добавление выпадающего списка в контейнер ===================== //
inputContainer.appendChild(platformSelect);



//----------------Единый контейнер для кнопок -------------------------//
const buttonContainer = document.createElement('div');
buttonContainer.style.display = 'flex'; // Используем flexbox для расположения кнопок в строку
buttonContainer.style.alignItems = 'baseline'; // Используем flexbox для расположения кнопок в строку
buttonContainer.style.alignContent = 'stretch';



buttonContainer.style.gap = '13px'; // Задаем промежуток между кнопками
buttonContainer.style.bottom = '113px'; // Отступ сверху для контейнера кнопок
buttonContainer.style.position = 'relative'; // Позиционирование относительно
buttonContainer.style.fontWeight = 'bold'; // Жирный текст для контейнера кнопок
buttonContainer.style.fontSize = '16px'; // Размер шрифта для кнопок
buttonContainer.style.width = '668px'; // Ширина кнопок (увеличена для эффекта растяжения




//-------------- Кнопка "Delete all" ------------------------//
const clearAllButton = document.createElement('button');
clearAllButton.innerText = 'Delete all'; // Текст на кнопке
clearAllButton.style.background = buttonColor; // Цвет фона кнопки
clearAllButton.style.color = '#fff'; // Цвет текста кнопки
clearAllButton.style.border = 'none'; // Убираем бордер у кнопки
clearAllButton.style.borderRadius = '4px'; // Скругленные углы кнопки
clearAllButton.style.padding = '5px 10px'; // Отступы внутри кнопки
clearAllButton.style.cursor = 'pointer'; // Курсор в виде руки при наведении
clearAllButton.style.boxShadow = buttonShadow; // Тень для кнопки "Delete all"

buttonContainer.appendChild(clearAllButton); // Добавляем кнопку в контейнер

// Обработчик события для кнопки "Delete all"
clearAllButton.onclick = () => {
    blockedEmotes = [];
    blockedChannels = [];
    GM_setValue("blockedEmotes", JSON.stringify(blockedEmotes, null, 2));
    GM_setValue("blockedChannels", JSON.stringify(blockedChannels, null, 2));
    console.log("[7BTV Control Emotes Panel] Очищены blockedEmotes и blockedChannels");
    updateBlockedList();
    updateCounter();
};


//----------------- export Button --------------------//
const exportButton = document.createElement('button');
exportButton.innerText = 'Export';
exportButton.style.background = buttonColor;
exportButton.style.color = '#fff';
exportButton.style.border = 'none';
exportButton.style.borderRadius = '4px';
exportButton.style.padding = '5px 10px';
exportButton.style.cursor = 'pointer';
exportButton.style.boxShadow = buttonShadow; // Тень для кнопки "Export"
buttonContainer.appendChild(exportButton);
exportButton.onclick = () => {
    const combinedData = {
        blockedEmotes: blockedEmotes,
        blockedChannels: blockedChannels
    };
    const blob = new Blob([JSON.stringify(combinedData, null, 2)], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    const link = document.createElement('a');
    link.href = url;
    link.download = 'blocked_data.json';
    link.click();
    URL.revokeObjectURL(url);
    console.log("[7BTV Control Emotes Panel] Экспортированы данные:", combinedData);
};


//================= importButton ========================//
// Перемещаем создание fileInput в глобальную область, чтобы избежать дублирования
let fileInput = null;

// Функция для создания кнопки "Import"
function createImportButton() {
    const button = document.createElement('button');
    button.innerText = 'Import';
    button.style.background = buttonColor;
    button.style.color = '#fff';
    button.style.border = 'none';
    button.style.borderRadius = '4px';
    button.style.padding = '5px 10px';
    button.style.cursor = 'pointer';
    button.style.boxShadow = buttonShadow;
    return button;
}

// Функция для создания или переиспользования элемента input типа "file"
function createFileInput() {
    if (!fileInput) {
        fileInput = document.createElement('input');
        fileInput.type = 'file';
        fileInput.accept = 'application/json';
        fileInput.style.display = 'none';
        fileInput.onchange = handleFileChange;
        document.body.appendChild(fileInput);
    }
    return fileInput;
}

// Инициализация кнопки "Import"
const importButton = createImportButton();
buttonContainer.appendChild(importButton);

importButton.onclick = () => {
    const input = createFileInput();
    input.value = ''; // Сбрасываем значение для повторного выбора файла
    input.click();
};

// Обработка изменений файла
function handleFileChange(event) {
    const file = event.target.files[0];
    if (!file) {
        console.log("[7BTV Control Emotes Panel] Файл не выбран");
        return;
    }
    const reader = new FileReader();
    reader.onload = handleFileLoad;
    reader.onerror = () => {
        console.error("[7BTV Control Emotes Panel] Ошибка чтения файла");
        alert('Ошибка при чтении файла!');
    };
    reader.readAsText(file);
}

// Обработка загрузки файла
function handleFileLoad(event) {
    try {
        const importedData = JSON.parse(event.target.result);

        if (!importedData || (!importedData.blockedEmotes && !importedData.blockedChannels)) {
            throw new Error('Неверный формат файла! Ожидается объект с blockedEmotes и/или blockedChannels');
        }

        processImportedData(importedData);
        updateInterface();
        console.log("[7BTV Control Emotes Panel] Импорт успешно завершен");
    } catch (err) {
        console.error('[7BTV Control Emotes Panel] Ошибка при парсинге файла:', err);
        alert(`Ошибка импорта: ${err.message}`);
    }
}

// Обработка импортированных данных
function processImportedData(importedData) {
    blockedEmotes = [];
    blockedChannels = [];
    blockedEmoteIDs.clear();
    blockedChannelIDs.clear();
    newlyAddedIds.clear();

    if (Array.isArray(importedData.blockedEmotes)) {
        importedData.blockedEmotes.forEach(emote => {
            const newId = emote.id && !blockedEmoteIDs.has(emote.id) && !blockedChannelIDs.has(emote.id)
                ? emote.id
                : generateRandomID();

            const newEmote = {
                id: newId,
                name: emote.name || emote.emoteUrl || '',
                platform: emote.platform || 'unknown',
                emoteName: emote.emoteName || getDefaultEmoteName(emote),
                emoteUrl: emote.emoteUrl || emote.name || '',
                date: emote.date || new Date().toISOString()
            };

            blockedEmotes.push(newEmote);
            blockedEmoteIDs.add(newId);
            newlyAddedIds.add(newId);
        });
    }

    if (Array.isArray(importedData.blockedChannels)) {
        importedData.blockedChannels.forEach(channel => {
            const newId = channel.id && !blockedChannelIDs.has(channel.id) && !blockedEmoteIDs.has(channel.id)
                ? channel.id
                : generateRandomID();

            const newChannel = {
                id: newId,
                name: channel.name || channel.emoteUrl || '',
                platform: channel.platform || 'TwitchChannel',
                emoteName: channel.emoteName || getDefaultEmoteName(channel),
                emoteUrl: channel.emoteUrl || channel.name || '',
                date: channel.date || new Date().toISOString()
            };

            blockedChannels.push(newChannel);
            blockedChannelIDs.add(newId);
            newlyAddedIds.add(newId);
        });
    }

    GM_setValue("blockedEmotes", JSON.stringify(blockedEmotes, null, 2));
    GM_setValue("blockedChannels", JSON.stringify(blockedChannels, null, 2));
    console.log("[7BTV Control Emotes Panel] Импортированы blockedEmotes:", blockedEmotes);
    console.log("[7BTV Control Emotes Panel] Импортированы blockedChannels:", blockedChannels);
}

// Функция обновления интерфейса
function updateInterface() {
    blockedEmotes = loadData("blockedEmotes", []);
    blockedChannels = loadData("blockedChannels", []);

    blockedEmoteIDs.clear();
    blockedChannelIDs.clear();
    blockedEmotes.forEach(emote => blockedEmoteIDs.add(emote.id));
    blockedChannels.forEach(channel => blockedChannelIDs.add(channel.id));

    updateBlockedList();
    updateCounter();

    const chatContainer = document.querySelector('.chat-scrollable-area__message-container');
    if (chatContainer) {
        toggleEmotesInNode(chatContainer); // Используем toggleEmotesInNode вместо hideEmotesForChannel
    } else {
        console.log(
            "%c[7BTV Control Emotes Panel]%c Контейнер чата не найден при обновлении интерфейса",
            'color:rgb(218, 93, 9); font-weight: bold;',
            'color: rgb(218, 93, 9);'
        );
    }
}

// Функция скрытия эмодзи в чате
function hideEmotesForChannel(chatContainer) {
    console.log("[7BTV Control Emotes Panel] Запуск hideEmotesForChannel");
    const emotes = chatContainer.querySelectorAll('.chat-line__message img, .chat-line__message .emote, .chat-line__message .bttv-emote, .chat-line__message .seventv-emote');

    emotes.forEach(emote => {
        const emoteUrl = emote.src || '';
        const emoteAlt = emote.getAttribute('alt') || '';
        let blockedEntry = null;

        // Проверяем, заблокирован ли эмодзи
        if (emoteUrl.includes('7tv.app')) {
            blockedEntry = blockedEmotes.find(e => e.platform === '7tv' && e.emoteUrl === emoteUrl);
        } else if (emoteUrl.includes('betterttv.net')) {
            blockedEntry = blockedEmotes.find(e => e.platform === 'bttTV' && e.emoteUrl === emoteUrl);
        } else if (emoteAlt) {
            blockedEntry = blockedChannels.find(e => e.platform === 'TwitchChannel' && emoteAlt.startsWith(e.name));
        }

        // Устанавливаем data-emote-id, если эмодзи заблокирован
        if (blockedEntry && !emote.getAttribute('data-emote-id')) {
            emote.setAttribute('data-emote-id', blockedEntry.id);
        }

        const emoteId = emote.getAttribute('data-emote-id');
        const isBlocked = emoteId && (blockedChannels.some(e => e.id === emoteId) || blockedEmotes.some(e => e.id === emoteId));

        // Скрываем или показываем эмодзи
        emote.style.display = isBlocked ? 'none' : '';
        console.log(`[7BTV Control Emotes Panel] Эмодзи ${emoteAlt || emoteUrl} (ID: ${emoteId || 'не установлен'}) ${isBlocked ? 'скрыт' : 'показан'}`);
    });
}

// Функция получения имени эмотикона по умолчанию
function getDefaultEmoteName(channel) {
    if (channel.platform === '7tv' || channel.platform === 'bttTV') {
        return channel.name.split('/').slice(-2, -1)[0] || 'No Name';
    } else if (channel.platform === 'ffz') {
        return channel.emoteName || channel.name.split('/').pop() || 'No Name';
    } else if (channel.platform === 'TwitchChannel') {
        return channel.name.split(/[^a-zA-Z0-9]/)[0] || 'No Name';
    } else {
        return 'No Name';
    }
}





// Добавляем кнопку "Unblock All Emotes" в контейнер кнопок
const unblockAllButton = document.createElement('button');
unblockAllButton.innerText = 'Unblock All Emotes';
unblockAllButton.style.background = buttonColor;
unblockAllButton.style.color = '#fff';
unblockAllButton.style.border = 'none';
unblockAllButton.style.borderRadius = '4px';
unblockAllButton.style.padding = '5px 10px';
unblockAllButton.style.cursor = 'pointer';
unblockAllButton.style.boxShadow = buttonShadow; // Тень для кнопки "Unblock All Emotes"
buttonContainer.appendChild(unblockAllButton);

// Добавляем кнопку "Back To Block All Emotes" в контейнер кнопок
const blockAllButton = document.createElement('button');
blockAllButton.innerText = 'Back To Block All Emotes';
blockAllButton.style.background = buttonColor;
blockAllButton.style.color = '#fff';
blockAllButton.style.border = 'none';
blockAllButton.style.borderRadius = '4px';
blockAllButton.style.padding = '5px 10px';
blockAllButton.style.cursor = 'pointer';
blockAllButton.style.boxShadow = buttonShadow; // Тень для кнопки "Back To Block All Emotes"
buttonContainer.appendChild(blockAllButton);

// Обработчик события для кнопки "Unblock All Emotes"
unblockAllButton.onclick = () => {
    const unblockedEmotes = GM_getValue('unblockedEmotes', []);
    const unblockedChannels = GM_getValue('unblockedChannels', []);
    if (blockedEmotes.length > 0 || blockedChannels.length > 0) {
        GM_setValue('unblockedEmotes', blockedEmotes);
        GM_setValue('unblockedChannels', blockedChannels);
        blockedEmotes = [];
        blockedChannels = [];
        GM_setValue('blockedEmotes', JSON.stringify(blockedEmotes, null, 2)); // Исправлено
        GM_setValue('blockedChannels', JSON.stringify(blockedChannels, null, 2)); // Исправлено
        console.log("[7BTV Control Emotes Panel] Разблокированы все: unblockedEmotes:", blockedEmotes, "unblockedChannels:", blockedChannels);
        updateBlockedList();
        updateCounter();
        showAllEmotes();
    }
};

// Функция для отображения всех смайлов в чате
function showAllEmotes() {
    const chatContainer = document.querySelector('.chat-scrollable-area__message-container');
    if (chatContainer) {
        const emotes = chatContainer.querySelectorAll('.chat-line__message img, .chat-line__message .emote, .chat-line__message .bttv-emote, .chat-line__message .seventv-emote');
        emotes.forEach(emote => {
            emote.style.display = ''; // Сбросить стиль display для отображения смайлов
        });
    }
}

// Обработчик события для кнопки "Back To Block All Emotes"
blockAllButton.onclick = () => {
    const unblockedEmotes = GM_getValue('unblockedEmotes', []);
    const unblockedChannels = GM_getValue('unblockedChannels', []);
    if (unblockedEmotes.length > 0 || unblockedChannels.length > 0) {
        blockedEmotes = unblockedEmotes;
        blockedChannels = unblockedChannels;
        GM_setValue('blockedEmotes', JSON.stringify(blockedEmotes));
        GM_setValue('blockedChannels', JSON.stringify(blockedChannels));
        GM_setValue('unblockedEmotes', []);
        GM_setValue('unblockedChannels', []);
        console.log("[7BTV Control Emotes Panel] Заблокированы все обратно: blockedEmotes:", blockedEmotes, "blockedChannels:", blockedChannels);

        // Обновляем список и счетчик
        updateBlockedList();
        updateCounter();

        // Применяем скрытие эмодзи в чате
        const chatContainer = document.querySelector('.chat-scrollable-area__message-container');
        if (chatContainer) {
            toggleEmotesInNode(chatContainer);
            console.log("[7BTV Control Emotes Panel] Применено скрытие эмодзи после восстановления блокировки");
        } else {
            console.log(
                "%c[7BTV Control Emotes Panel]%c Контейнер чата не найден при восстановлении блокировки",
                'color:rgb(218, 93, 9); font-weight: bold;',
                'color: rgb(218, 93, 9);'
            );
        }
    }
};



// Кнопка "Show Stats Chart"
const showStatsButton = document.createElement('button');
showStatsButton.innerText = 'Show Stats Chart';
showStatsButton.style.cursor = 'pointer';
showStatsButton.style.position = 'relative';
showStatsButton.style.right = '1%';



// Создаём модальное окно для диаграммы
const chartModal = document.createElement('div');
chartModal.style.position = 'fixed';
chartModal.style.top = '35%';
chartModal.style.left = '35%';
chartModal.style.width = '35%';
chartModal.style.height = '55%';
chartModal.style.display = 'none'; // Скрыто по умолчанию
chartModal.style.justifyContent = 'center';
chartModal.style.alignItems = 'center';
chartModal.style.zIndex = '10001';

// Создаём контейнер для диаграммы
const chartContainer = document.createElement('div');
chartContainer.style.background = 'linear-gradient(315deg, hsla(285, 61%, 12%, 1) 0%, hsla(186, 26%, 21%, 1) 55%, hsla(284, 9%, 48%, 1) 100%)';chartContainer.style.padding = '20px';
chartContainer.style.borderRadius = '20px';
chartContainer.style.boxShadow = '16px 20px 20px 5px #0000008c';
chartContainer.style.border = '2px solid #24888e';
chartContainer.style.position = 'relative';
chartContainer.style.width = '600px';
chartContainer.style.maxHeight = '80vh';
chartContainer.style.overflowY = 'auto';

// Создаём кнопку закрытия модального окна
const closeChartButton = document.createElement('button');
closeChartButton.innerText = 'Close';
closeChartButton.style.position = 'absolute';
closeChartButton.style.top = '10px';
closeChartButton.style.right = '10px';
closeChartButton.style.background = '#944646';
closeChartButton.style.color = '#fff';
closeChartButton.style.border = 'none';
closeChartButton.style.borderRadius = '4px';
closeChartButton.style.padding = '5px 10px';
closeChartButton.style.cursor = 'pointer';
closeChartButton.onclick = () => {
    chartModal.style.display = 'none';
    // Уничтожаем диаграмму, чтобы избежать утечек памяти
    const existingChart = Chart.getChart('statsChart');
    if (existingChart) {
        existingChart.destroy();
    }
};

// Создаём элемент canvas для диаграммы
const chartCanvas = document.createElement('canvas');
chartCanvas.id = 'statsChart';
chartCanvas.style.maxWidth = '100%';
chartCanvas.style.height = '400px';

// Добавляем элементы в модальное окно
chartContainer.appendChild(closeChartButton);
chartContainer.appendChild(chartCanvas);
chartModal.appendChild(chartContainer);
document.body.appendChild(chartModal);

// Обработчик клика на кнопку "Show Stats Chart"
showStatsButton.onclick = () => {
    // Показываем модальное окно
    chartModal.style.display = 'flex';

    // Собираем данные для диаграммы
    const twitchCount = blockedChannels.length;
    const bttvCount = blockedEmotes.filter(channel => channel.platform === 'bttTV').length;
    const tv7Count = blockedEmotes.filter(channel => channel.platform === '7tv').length;
    const ffzCount = blockedEmotes.filter(channel => channel.platform === 'ffz').length;

    // Данные для диаграммы
    const chartData = {
        labels: ['Twitch', 'BTTV', '7TV', 'FFZ'],
        datasets: [{
            label: 'Blocked Emotes by Platform',
            data: [twitchCount, bttvCount, tv7Count, ffzCount],
            backgroundColor: [
                'rgba(96, 37, 136, 0.6)',  // Twitch
                'rgba(214, 95, 91, 0.6)',  // BTTV
                'rgba(34, 196, 196, 0.6)',  // 7TV
                'rgba(121, 117, 117, 0.66)'   // FFZ
            ],
            borderColor: [
                'rgb(130, 255, 99)',
                'rgb(97, 183, 240)',
                'rgb(255, 238, 86)',
                'rgb(74, 221, 221)'
            ],
            borderWidth: 1
        }]
    };

    // Уничтожаем старую диаграмму, если она существует
    const existingChart = Chart.getChart('statsChart');
    if (existingChart) {
        existingChart.destroy();
    }

    // Создаём новую диаграмму
    new Chart(chartCanvas, {
        type: 'bar',
        data: chartData,
        options: {
            responsive: true,
            maintainAspectRatio: false,
            plugins: {
                legend: {
                    position: 'top',
                    labels: {
                        color: '#E5E7EB' // Цвет текста легенды
                    }
                },
                title: {
                    display: true,
                    text: 'Blocked Emotes by Platform',
                    color: ' #E5E7EB' // Цвет текста заголовка
                }
            },
            scales: {
                y: {
                    beginAtZero: true,
                    title: {
                        display: true,
                        text: 'Number of Blocked Emotes',
                        color: ' #E5E7EB' // Цвет текста заголовка оси Y
                    },
                    ticks: {
                        color: ' #E5E7EB' // Цвет текста значений на оси Y
                    }
                },
                x: {
                    title: {
                        display: true,
                        text: 'Platform',
                        color: ' #E5E7EB' // Цвет текста заголовка оси X
                    },
                    ticks: {
                        color: ' #E5E7EB' // Цвет текста значений на оси X
                    }
                }
            }
        }
    });
};


//======================= Счётчик ========================//
const counter = document.createElement('div');
counter.style.display = 'flex';
counter.style.flexDirection = 'row';
counter.style.justifyContent = 'center';
counter.style.width = '460px';
counter.style.backgroundColor = ' #b69dcf'; // Белый фон
counter.style.color = ' #4c2a5e'; // Цвет текста (темно-фиолетовый)
counter.style.border = '3px solid #4c2a5e'; // Граница того же цвета, что и текст
counter.style.borderRadius = '8px'; // Радиус скругления границы
counter.style.padding = '5px 0px'; // Отступы для удобства
counter.style.marginLeft = '6px'; // Отступ слева для отделения от других элементов
counter.style.fontWeight = 'bold'; // Жирное начертание текста
counter.style.fontSize = '16px'; // Устанавливаем размер шрифта для лучшей видимости
counter.style.bottom = '545px'; // Обновленное положение сверху
counter.style.left = '202px'; // Обновленное положение справа
counter.style.position = 'relative '; // Относительное позиционирование для точного расположения

controlPanel.appendChild(counter);

// Функция для обновления счётчика
function updateCounter() {
    const twitchCount = blockedChannels.length;
    const bttvCount = blockedEmotes.filter(channel => channel.platform === 'bttTV').length;
    const tv7Count = blockedEmotes.filter(channel => channel.platform === '7tv').length;
    const ffzCount = blockedEmotes.filter(channel => channel.platform === 'ffz').length;
    const totalCount = twitchCount + bttvCount + tv7Count + ffzCount;
    counter.innerText = `Twitch: ${twitchCount} | BTTV: ${bttvCount} | 7TV: ${tv7Count} | FFZ: ${ffzCount} | Total: ${totalCount}`;
}

// Добавляем элементы на страницу
inputContainer.appendChild(input);
inputContainer.appendChild(addButton);
controlPanel.appendChild(inputContainer);

// Перемещаем контейнер кнопок вниз
controlPanel.appendChild(buttonContainer);

document.body.appendChild(controlPanel);

// Вызываем функцию обновления счётчика
updateCounter();





// Загружаем сохранённое состояние переключателя из хранилища

//============= Создаем кнопку "Open Blocker Emote" ===================//
const openPanelButton = document.createElement('button');
openPanelButton.innerText = 'panel control emotes';
openPanelButton.style.fontWeight = 'bold';
openPanelButton.style.top = '22px';
openPanelButton.style.right = '1344px';
openPanelButton.style.position = 'fixed'; // Фиксированное положение
openPanelButton.style.width = '200px'; // Фиксированная ширина кнопки
openPanelButton.style.height = '41px'; // Фиксированная высота кнопки
openPanelButton.style.background = ' #5d5d5d'; // Цвет кнопки
openPanelButton.style.color = ' #171c1c';
openPanelButton.style.border = 'none'; // Без границ
openPanelButton.style.borderRadius = '20px'; // Закругленные углы
openPanelButton.style.padding = '10px';
openPanelButton.style.cursor = 'pointer';
openPanelButton.style.zIndex = 10000; // Высокий z-index
openPanelButton.style.transition = 'background 0.3s ease'; // Плавное изменение фона
openPanelButton.style.display = 'flex';
openPanelButton.style.alignItems = 'center';
openPanelButton.style.justifyContent = 'space-between'; // Чтобы текст и переключатель были по разным краям

// Создаем контейнер для переключателя (темная рамка)
const switchContainer = document.createElement('div');
switchContainer.style.width = '44px'; // Увеличиваем ширину контейнера на 6px
switchContainer.style.height = '27px'; // Увеличиваем высоту контейнера на 6px
switchContainer.style.borderRadius = '13px'; // Скругленные углы
switchContainer.style.backgroundColor = ' #171c1c';  // Темно сеая рамка для кружка
switchContainer.style.position = 'relative'; // Для абсолютного позиционирования кружка
switchContainer.style.transition = 'background 0.3s ease'; // Плавное изменение фона контейнера
openPanelButton.appendChild(switchContainer);

// Создаем фиолетовый кружок (переключатель кружок )
const switchCircle = document.createElement('div');
switchCircle.style.width = '19px'; // Увеличиваем ширину кружка на 3px
switchCircle.style.height = '19px'; // Увеличиваем высоту кружка на 3px
switchCircle.style.borderRadius = '50%'; // Кружок
switchCircle.style.backgroundColor = ' #5d5d5d'; // темно Серый  цвет кружка
switchCircle.style.boxShadow = '0 2px 6px rgba(0, 0, 0, 0.8)'; // Тень для кружка
switchCircle.style.position = 'absolute'; // Абсолютное позиционирование внутри контейнера
switchCircle.style.top = '3px'; // Отступ сверху
switchCircle.style.left = '3px'; // Отступ слева
switchCircle.style.transition = 'transform 0.3s ease'; // Плавное движение
switchContainer.appendChild(switchCircle);

// Функция для обновления состояния переключателя
const updateSwitchState = () => {
    if (isPanelOpen) {
        openPanelButton.style.background = ' #5d5d5d'; // Цвет кнопки при открытой панели
        switchCircle.style.transform = 'translateX(20px)'; // Перемещаем кружок вправо
        switchContainer.style.backgroundColor = ' #464646'; // Цвет контейнера в включённом состоянии
        controlPanel.style.display = 'block'; // Показываем панель
        controlPanel.style.height = '656px'; // Устанавливаем полную высоту
    } else {
        openPanelButton.style.background = ' #5d5d5d'; // Цвет кнопки при закрытой панели
        switchCircle.style.transform = 'translateX(0)'; // Перемещаем кружок влево
        switchContainer.style.backgroundColor = ' #171c1c'; // Цвет контейнера в выключенном состоянии
        controlPanel.style.display = 'none'; // Скрываем панель
        controlPanel.style.height = '0px'; // Сворачиваем панель
    }
};

// Обработчик клика для переключения состояния панели
openPanelButton.onclick = () => {
    isPanelOpen = !isPanelOpen; // Переключаем состояние
    GM_setValue('isPanelOpen', isPanelOpen); // Сохраняем состояние
    updateSwitchState(); // Обновляем видимость и переключатель
};


// Инициализация состояния при загрузке
window.addEventListener('load', () => {
    document.body.appendChild(openPanelButton);
    updateSwitchState(); // Устанавливаем начальное состояние панели и переключателя

    const updateButtonPosition = () => {
        const windowWidth = window.innerWidth;
        const windowHeight = window.innerHeight;
        openPanelButton.style.top = `${windowHeight * 0.005}px`; // 5% от высоты окна
        openPanelButton.style.right = `${windowWidth * 0.2}px`; // 20% от ширины окна
    };

    updateButtonPosition();
    window.addEventListener('resize', updateButtonPosition);
});







//=============== Блокировка и Запуск скрытия эмодзи в чате ==================//

//=============== Генерация случайного ID ===============//
function generateRandomID() {
    const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    const randomLength = Math.floor(Math.random() * 67) + 1; // Случайная длина от 1 до 68
    let randomID = '';
    for (let i = 0; i < randomLength; i++) {
        randomID += characters.charAt(Math.floor(Math.random() * characters.length));
    }
    return `emote_${randomID}`;
}



// Оптимизированная версия toggleEmotesInNode
const debouncedToggleEmotes = debounce(toggleEmotesInNode, 100);

async function toggleEmotesInNode(node) {
    try {
        console.log(`%c[${new Date().toISOString()}] %c[7BTV Control Emotes Panel] %ctoggleEmotesInNode - starting`,
            'color: rgb(63, 136, 219);',
            'color: rgb(52, 163, 148); font-weight: bold;');

        const emotes = node.querySelectorAll('.chat-line__message img, .chat-line__message .emote, .chat-line__message .bttv-emote, .chat-line__message .seventv-emote');
        console.log(`[7BTV Control Emotes Panel] Найдено эмодзи для обработки: ${emotes.length}`);

        for (const emote of emotes) {
            const emoteUrl = emote.src || emote.getAttribute('srcset')?.split(' ')[0] || '';
            const emoteAlt = emote.getAttribute('alt') || '';
            let blockedEntry = null;

            if (emoteUrl.includes('7tv.app')) {
                blockedEntry = blockedEmotes.find(e => e.platform === '7tv' && e.emoteUrl === emoteUrl);
            } else if (emoteUrl.includes('betterttv.net')) {
                blockedEntry = blockedEmotes.find(e => e.platform === 'bttTV' && e.emoteUrl === emoteUrl);
            } else if (emoteUrl.includes('frankerfacez.com')) {
                blockedEntry = blockedEmotes.find(e => e.platform === 'ffz' && e.emoteUrl === emoteUrl);
            } else if (emoteAlt) {
                blockedEntry = blockedChannels.find(e => e.platform === 'TwitchChannel' && emoteAlt.startsWith(e.name));
            }

            if (blockedEntry && !emote.getAttribute('data-emote-id')) {
                emote.setAttribute('data-emote-id', blockedEntry.id);
            }

            const emoteId = emote.getAttribute('data-emote-id');
            const isBlocked = emoteId && (blockedChannels.some(e => e.id === emoteId) || blockedEmotes.some(e => e.id === emoteId));

            emote.style.display = isBlocked ? 'none' : '';
            console.log(`[7BTV Control Emotes Panel] Эмодзи ${emoteAlt || emoteUrl} (ID: ${emoteId || 'не установлен'}) ${isBlocked ? 'скрыт' : 'показан'}`);
        }

        console.log(`%c[${new Date().toISOString()}] %c[7BTV Control Emotes Panel] %ctoggleEmotesInNode - completed`,
            'color: rgb(63, 136, 219);',
            'color: rgb(52, 163, 148); font-weight: bold;');
    } catch (error) {
        console.error(`[ERROR] Ошибка в toggleEmotesInNode:`, error);
    }
}
// Используем дебаунс в наблюдателе
const observer = new MutationObserver(mutations => {
    mutations.forEach(mutation => {
        mutation.addedNodes.forEach(node => {
            if (node.nodeType === 1) {
                console.log(`%cНовый узел добавлен в DOM`,
                    'color:rgb(29, 202, 136) ;');
                debouncedToggleEmotes(node);
            }
        });
    });
});



function observeChatContainer() {
    const chatContainer = document.querySelector('.chat-scrollable-area__message-container');
    if (chatContainer) {
        // Успешно - зеленый цвет
           console.log(
             '%c[7BTV Control Emotes Panel]%c Контейнер чата найден, начинаем наблюдение',
             'color: #00C4B4; font-weight: bold;', // Стиль для [7BTV Control Emotes Panel]
             'color: #00C4B4;' // Стиль для остального текста
           );
        observer.disconnect(); // Останавливаем старое наблюдение
        observer.observe(chatContainer, { childList: true, subtree: true });
        toggleEmotesInNode(chatContainer); // Проверяем существующие сообщения
    } else {
        // Неуспешно  - красный цвет
            console.log(
              '%c[7BTV Control Emotes Panel]%c Контейнер чата не найден, повторная попытка через 500мс',
              'color: #FF5555; font-weight: bold;', // Стиль для [7BTV Control Emotes Panel]
              'color: #FF5555;' // Стиль для остального текста
            );
        setTimeout(observeChatContainer, 500);
    }
}

// Добавляем наблюдение за изменениями на более высоком уровне DOM
function startRootObserver() {
    const rootObserver = new MutationObserver(() => {
        const chatContainer = document.querySelector('.chat-scrollable-area__message-container');
        // Состояние контейнера чата - зеленый если найден, красный если не найден
           console.log(
             '%c[7BTV Control Emotes Panel]%c RootObserver: контейнер чата %c' + (chatContainer ? 'найден' : 'не найден'),
             'color: #1E90FF; font-weight: bold;', // Стиль для [7BTV Control Emotes Panel] (DodgerBlue)
             'color: #1E90FF;', // Стиль для "RootObserver: контейнер чата"
             `color: ${chatContainer ? '#00C4B4' : '#FF5555'}; font-weight: bold;` // Зеленый (#00C4B4) или красный (#FF5555) для статуса
           );

        if (chatContainer) {
            observeChatContainer();
        }
    });
    rootObserver.observe(document.body, { childList: true, subtree: true });
    // Запуск RootObserver - синий цвет (информационный)
         console.log(
           '%c[7BTV Control Emotes Panel]%c RootObserver запущен',
           'color: #1E90FF; font-weight: bold;', // Стиль для [7BTV Control Emotes Panel] (DodgerBlue)
           'color: #1E90FF;' // Стиль для остального текста
         );

}

// Запускаем наблюдение
startRootObserver();


let lastUrl = location.href;

function checkUrlChange() {
    const currentUrl = location.href;
    if (currentUrl !== lastUrl) {
        console.log('[7BTV Control Emotes Panel] URL изменился, перезапускаем наблюдение за чатом');
        ContextMenuManager.removeMenu(); // Удаляем контекстное меню
        lastUrl = currentUrl;
        observeChatContainer();
    }
    setTimeout(checkUrlChange, 1000);
}

checkUrlChange();




//=============== Контекстное меню ===============//
const contextMenuStyle = document.createElement('style');
contextMenuStyle.innerHTML = `
  .custom-context-menu {
     position: absolute;
     background:rgb(19, 88, 39);
     border: 1px solid #ccc;
     padding: 5px;
     z-index: 10002;
     cursor: pointer;
     color: #fff;
     transition: background 0.3s ease;
     user-select: none;
     min-width: 150px;
     box-shadow: 0 2px 8px 2px #8BC34A;
     border-radius: 8px;
   }
     .custom-context-menu:hover {
        background:rgb(16, 68, 30);
   }
`;
document.head.appendChild(contextMenuStyle);

const ContextMenuManager = {
    menu: null,
    isProcessing: false, // Флаг для предотвращения многократных нажатий

    createMenu(event, emotePrefix, platform, emoteName) {
        this.removeMenu();
        const menu = document.createElement('div');
        menu.className = 'custom-context-menu';
        menu.style.top = `${event.pageY}px`;
        menu.style.left = `${event.pageX}px`;
        menu.innerText = `Block Emote (${emoteName || 'Unknown'})`;
        console.log(`%c[${new Date().toISOString()}] %c[7BTV Control Emotes Panel] %cContext menu created at:`,
            'color: rgb(85, 113, 165);',
            'color: rgb(85, 113, 165); font-weight: bold;',
            'color: rgb(85, 113, 165);', event.pageX, event.pageY);

        document.body.appendChild(menu);
        this.menu = menu;

        menu.addEventListener('click', (e) => {
            e.stopPropagation();
            if (this.isProcessing) return; // Пропускаем, если обработка уже идет
            this.isProcessing = true;

            console.log(`%c[${new Date().toISOString()}] %c[7BTV Control Emotes Panel] %cBlocking emote: ${emoteName}`,
                'color: rgb(209, 89, 129);',
                'color: rgb(255, 50, 50); font-weight: bold;',
                'color: rgb(209, 89, 129);');

            this.blockEmote(emotePrefix, platform, emoteName);
            this.removeMenu();
            this.isProcessing = false;
        });

        document.addEventListener('click', (e) => {
            if (!menu.contains(e.target)) this.removeMenu();
        }, { once: true });
    },

    removeMenu() {
        if (this.menu) {
            console.log(`%c[${new Date().toISOString()}] %c[7BTV Control Emotes Panel] %cRemoving context menu`,
                'color: rgb(209, 89, 129);',
                'color: rgb(115, 2, 160); font-weight: bold;',
                'color: white;');
            this.menu.remove();
            this.menu = null;
        }
    },

    blockEmote(emotePrefix, platform, emoteName) {
        const emoteId = generateRandomID();
        const currentDateTime = new Date().toISOString();
        const newEntry = {
            id: emoteId,
            name: emotePrefix, // Префикс (например, "guwu")
            platform: platform,
            emoteName: emoteName || emotePrefix.split('/').pop() || 'Unknown', // Полное название (например, "guwuPopcorn")
            emoteUrl: platform === 'TwitchChannel' ? emotePrefix : emotePrefix, // Для Twitch используем префикс как URL
            date: currentDateTime
        };

        const isDuplicate = platform === 'TwitchChannel'
            ? blockedChannels.some(e => e.name === newEntry.name && e.platform === newEntry.platform)
            : blockedEmotes.some(e => e.emoteUrl === newEntry.emoteUrl && e.platform === newEntry.platform);

        if (isDuplicate) {
            console.log(`%c[7BTV Control Emotes Panel] %cEmote already blocked: ${newEntry.emoteName}`,
                'color: rgb(255, 165, 0); font-weight: bold;',
                'color: rgb(255, 165, 0);');
            return;
        }

        if (platform === 'TwitchChannel') {
            blockedChannels.push(newEntry);
            blockedChannelIDs.add(emoteId);
            newlyAddedIds.add(emoteId);
            GM_setValue("blockedChannels", JSON.stringify(blockedChannels, null, 2));
            console.log(`%c[7BTV Control Emotes Panel] %cAdded to blockedChannels:`,
                'color: rgb(0, 255, 0); font-weight: bold;',
                'color: rgb(0, 255, 0);', newEntry);
        } else {
            blockedEmotes.push(newEntry);
            blockedEmoteIDs.add(emoteId);
            newlyAddedIds.add(emoteId);
            GM_setValue("blockedEmotes", JSON.stringify(blockedEmotes, null, 2));
            console.log(`%c[7BTV Control Emotes Panel] %cAdded to blockedEmotes:`,
                'color: rgb(0, 255, 0); font-weight: bold;',
                'color: rgb(0, 255, 0);', newEntry);
        }

        const chatContainer = document.querySelector('.chat-scrollable-area__message-container');
        if (chatContainer) {
            toggleEmotesInNode(chatContainer);
        }

        updateBlockedList();
        updateCounter();
    }
};

//=============== Обработчик контекстного меню ===============//
// блокировка сайлов правой кнопкой //
document.addEventListener('contextmenu', (event) => {
    const target = event.target;
    if (target.tagName === 'IMG' && target.closest('.chat-line__message')) {
        event.preventDefault();
        const emoteUrl = target.src || target.getAttribute('srcset')?.split(' ')[0] || '';
        const emoteAlt = target.getAttribute('alt') || '';
        const dataProvider = target.getAttribute('data-provider') || '';
        let emotePrefix = '';
        let platform = '';
        let emoteName = emoteAlt;

        console.log(`[${new Date().toISOString()}] [7BTV Control Emotes Panel] Context menu triggered for:`, emoteUrl, emoteAlt, 'data-provider:', dataProvider);

        // Определяем платформу и префикс
        if (dataProvider === 'bttv' && emoteUrl.includes('betterttv.net')) {
            emotePrefix = emoteUrl || `https://cdn.betterttv.net/emote/${target.getAttribute('data-id')}/2x.webp`;
            platform = 'bttTV';
            console.log("[7BTV Control Emotes Panel] Detected bttv emote (via data-provider):", emotePrefix);
        } else if (dataProvider === 'ffz' && emoteUrl.includes('frankerfacez.com')) {
            emotePrefix = emoteUrl || `https://cdn.frankerfacez.com/emote/${target.getAttribute('data-id')}/2`;
            platform = 'ffz';
            emoteName = emoteAlt;
            console.log("[7BTV Control Emotes Panel] Detected ffz emote (via data-provider):", emotePrefix);
        } else if (dataProvider === 'ffz' && emoteUrl.includes('7tv.app')) {
            emotePrefix = emoteUrl || `https://cdn.7tv.app/emote/${target.getAttribute('data-id')}/2x.webp`;
            platform = '7tv';
            console.log("[7BTV Control Emotes Panel] Detected 7tv emote (via data-provider):", emotePrefix);
        } else if (emoteUrl.includes('betterttv.net')) {
            emotePrefix = emoteUrl;
            platform = 'bttTV';
            console.log("[7BTV Control Emotes Panel] Detected bttv emote (via URL):", emoteUrl);
        } else if (emoteUrl.includes('7tv.app')) {
            emotePrefix = emoteUrl;
            platform = '7tv';
            console.log("[7BTV Control Emotes Panel] Detected 7tv emote (via URL):", emoteUrl);
        } else if (emoteUrl.includes('frankerfacez.com')) {
            emotePrefix = emoteUrl;
            platform = 'ffz';
            emoteName = emoteAlt;
            console.log("[7BTV Control Emotes Panel] Detected ffz emote (via URL):", emoteUrl);
        } else if (emoteAlt) {
            // Обновленная логика для TwitchChannel
            const match = emoteAlt.match(/^([a-z0-9]+)([A-Z].*)$/); // Ищем префикс до первой заглавной буквы
            if (match) {
                emotePrefix = match[1]; // Например, "lowti3" из "lowti3Face3"
                emoteName = emoteAlt;   // Полное название, например "lowti3Face3"
            } else {
                // Если не удалось разделить, используем первую группу символов до не-букв/цифр как запасной вариант
                emotePrefix = emoteAlt.split(/[^a-zA-Z0-9]/)[0] || emoteAlt;
                emoteName = emoteAlt;
            }
            platform = 'TwitchChannel';
            console.log("[7BTV Control Emotes Panel] Detected TwitchChannel emote:", emoteAlt, "prefix:", emotePrefix);
        }

        if (emotePrefix && platform) {
            console.log(`[7BTV Control Emotes Panel] Creating context menu for emote with prefix: ${emotePrefix}, platform: ${platform}`);
            ContextMenuManager.createMenu(event, emotePrefix, platform, emoteName);
        } else {
            console.log("[7BTV Control Emotes Panel] Could not determine platform or prefix, using fallback TwitchChannel");
            ContextMenuManager.createMenu(event, emoteAlt || emoteUrl, 'TwitchChannel', emoteAlt || 'Unknown');
        }
    }
});

//=============== Запуск ===============//
observeChatContainer();







//====================== Управление высотой панели =======================
function closePanel() {
    isPanelOpen = false;
    GM_setValue('isPanelOpen', isPanelOpen);
    controlPanel.style.height = '0px'; // Плавно уменьшаем высоту
    setTimeout(() => {
        if (!isPanelOpen) controlPanel.style.display = 'none'; // Полностью скрываем после завершения анимации
    }, 150); // Таймер соответствует времени анимации
}

//----------------- Анимация сворачивания панели-------------------------
function openPanel() {
    isPanelOpen = true;
    GM_setValue('isPanelOpen', isPanelOpen);
    controlPanel.style.display = 'block'; // Делаем панель видимой
    setTimeout(() => {
        controlPanel.style.height = '656px'; // Плавно увеличиваем высоту
    }, 0); // Устанавливаем высоту с задержкой для работы анимации
}

//========================== Переключение состояния панели Управления 'openPanelButton' ===============================
openPanelButton.onclick = () => {
    isPanelOpen = !isPanelOpen; // Переключаем состояние панели (открыта/закрыта)
    GM_setValue('isPanelOpen', isPanelOpen);

    // Перемещаем переключатель (круглый элемент), когда панель открывается или закрывается
    switchCircle.style.transform = isPanelOpen ? 'translateX(20px)' : 'translateX(0)';

    // Меняем цвет фона контейнера в зависимости от состояния панели
     // switchContainer.style.backgroundColor = isPanelOpen ? ' #9e9e9e' : ' #171c1c'; //
     // закоментируем убрав  временно для будущих версий  switchContainer //

    // Переключаем видимость панели: открываем или закрываем
    if (isPanelOpen) {
        openPanel(); // Вызов функции для открытия панели
    } else {
        closePanel(); // Вызов функции для закрытия панели
    }
};

// Инициализация состояния
updateSwitchState(); // Убедимся, что переключатель синхронизирован с начальным состоянием
updateBlockedList();
updateCounter();





//============== Минипанель с кнопками сортировки по категориям =================//
const sortContainer = document.createElement('div');
sortContainer.id = 'sortContainer';
sortContainer.style.display = 'flex';
sortContainer.style.justifyContent = 'space-around';
sortContainer.style.backgroundColor = ' rgb(89 51 114)';
sortContainer.style.padding = '5px';
sortContainer.style.marginBottom = '37px';
sortContainer.style.position = 'relative';
sortContainer.style.top = '57px';
sortContainer.style.borderRadius = '8px 8px 0 0'; // Закругление только верхних углов
sortContainer.style.border = '1px solid rgb(255, 255, 255)';
sortContainer.style.boxShadow = ' rgb(0 0 0 / 0%) 0px 15px 6px 0px'; // Использование RGBA для прозрачности
sortContainer.style.zIndex = 'inherit'; // Наследует z-index от родителя

// Определение начальных значений для currentSortOrder
let currentSortOrder = {
    name: 'asc',
    platform: 'asc',
    date: 'asc'
};

// Кнопки сортировки
const sortByNameButton = document.createElement('button');
sortByNameButton.innerHTML = 'Name ▲';
sortByNameButton.style.cursor = 'pointer';
sortByNameButton.style.position = 'relative';
sortByNameButton.style.left = '13%';

sortByNameButton.onclick = () => {
    const order = currentSortOrder.name === 'asc' ? 'desc' : 'asc';
    currentSortOrder.name = order;
    sortByNameButton.innerHTML = `Name ${order === 'asc' ? '▲' : '▼'}`; // Переключение стрелочки
    sortblockedEmotes('name', order);
};
sortContainer.appendChild(sortByNameButton);

const sortByPlatformButton = document.createElement('button');
sortByPlatformButton.innerHTML = 'Platform ▲';
sortByPlatformButton.style.cursor = 'pointer';
sortByPlatformButton.style.position = 'relative';
sortByPlatformButton.style.right = '118px';

sortByPlatformButton.onclick = () => {
    const order = currentSortOrder.platform === 'asc' ? 'desc' : 'asc';
    currentSortOrder.platform = order;
    sortByPlatformButton.innerHTML = `Platform ${order === 'asc' ? '▲' : '▼'}`;
    sortblockedEmotes('platform', order);
};
sortContainer.appendChild(sortByPlatformButton);

const sortByDateButton = document.createElement('button');
sortByDateButton.innerHTML = 'Date-Time ▲';
sortByDateButton.style.cursor = 'pointer';
sortByDateButton.style.top = '0px';
sortByDateButton.style.position = 'relative';
sortByDateButton.style.left = '9px';
sortByDateButton.onclick = () => {
    const order = currentSortOrder.date === 'asc' ? 'desc' : 'asc';
    currentSortOrder.date = order;
    sortByDateButton.innerHTML = `Date ${order === 'asc' ? '▲' : '▼'}`;
    sortblockedEmotes('date', order);
};
sortContainer.appendChild(sortByDateButton);

// Добавляем контейнер сортировки в панель управления
controlPanel.insertBefore(sortContainer, title);


// ---------- goToLast    Button ------------- //
const goToLastButton = document.createElement('button');
goToLastButton.innerHTML = 'Go To Last Element ▼'; // Короткое название
goToLastButton.style.cursor = 'pointer';
goToLastButton.style.position = 'relative';
goToLastButton.style.right = '2%'; // Сдвигаем чуть левее для баланса

goToLastButton.onclick = () => {
    goToLastAddedItem();
};
sortContainer.appendChild(goToLastButton);
sortContainer.appendChild(showStatsButton);




//============== Функция для сортировки списка =================//
function sortblockedEmotes(criteria, order) {
    const sortFunc = (a, b) => {
        let comparison = 0;
        if (criteria === 'name') {
            comparison = a.emoteName.localeCompare(b.emoteName);
        } else if (criteria === 'platform') {
            comparison = a.platform.localeCompare(b.platform);
        } else if (criteria === 'date') {
            comparison = new Date(a.date) - new Date(b.date);
        }
        return order === 'asc' ? comparison : -comparison;
    };

    // Сортируем оба массива
    blockedEmotes.sort(sortFunc);
    blockedChannels.sort(sortFunc);

    // Обновляем интерфейс после сортировки
    updateBlockedList();
}
//============== Обработчики событий для кнопок =================//
const buttons = [addButton, clearAllButton, exportButton, importButton, unblockAllButton, blockAllButton];
buttons.forEach(button => {
    button.onmouseover = function() {
        button.style.background = '-webkit-linear-gradient(135deg, #443157 0%,rgb(90, 69, 122) 56%, #443157 98%, #443157 100%)'; // Изменение фона при наведении
    };
    button.onmouseout = function() {
        button.style.background = buttonColor; // Возвращаем исходный цвет
    };
});



// ========= Функция для прокрутки к последнему добавленному элементу ============= //
function goToLastAddedItem() {
    const allItems = [...blockedEmotes, ...blockedChannels];
    if (allItems.length === 0) {
        console.log("[7BTV Control Emotes Panel] Список пуст, некуда прокручивать");
        return;
    }

    // Находим элемент с самой поздней датой
    const lastItem = allItems.reduce((latest, current) => {
        return new Date(current.date) > new Date(latest.date) ? current : latest;
    });

    // Ищем элемент в DOM по его ID
    let lastElement = list.querySelector(`[data-id="${lastItem.id}"]`);
    if (lastElement) {
        // Подсвечиваем элемент
        lastElement.classList.add('last-item-highlight');

        // Прокручиваем к элементу
        const itemOffsetTop = lastElement.offsetTop;
        const listHeight = list.clientHeight;
        const itemHeight = lastElement.clientHeight;
        const scrollPosition = itemOffsetTop - (listHeight / 2) + (itemHeight / 2);
        list.scrollTo({
            top: scrollPosition,
            behavior: 'smooth'
        });

        // Убираем подсветку через 60 секунд
        setTimeout(() => {
            lastElement.classList.remove('last-item-highlight');
            console.log(`[7BTV Control Emotes Panel] Подсветка убрана с элемента: ${lastItem.emoteName}`);
        }, 60000); // 60000 мс = 1 минута

        console.log(`[7BTV Control Emotes Panel] Прокручено и подсвечено: ${lastItem.emoteName} (ID: ${lastItem.id})`);
    } else {
        console.log("[7BTV Control Emotes Panel] Последний элемент не найден в DOM, обновляем список");
        updateBlockedList();
        setTimeout(() => {
            lastElement = list.querySelector(`[data-id="${lastItem.id}"]`);
            if (lastElement) {
                lastElement.classList.add('last-item-highlight');
                const itemOffsetTop = lastElement.offsetTop;
                const listHeight = list.clientHeight;
                const itemHeight = lastElement.clientHeight;
                const scrollPosition = itemOffsetTop - (listHeight / 2) + (itemHeight / 2);
                list.scrollTo({
                    top: scrollPosition,
                    behavior: 'smooth'
                });
                setTimeout(() => {
                    lastElement.classList.remove('last-item-highlight');
                    console.log(`[7BTV Control Emotes Panel] Подсветка убрана с элемента после обновления: ${lastItem.emoteName}`);
                }, 60000);
                console.log(`[7BTV Control Emotes Panel] Успешно прокручено и подсвечено после обновления: ${lastItem.emoteName}`);
            }
        }, 100);
    }
}

console.log(getComputedStyle(controlPanel).display);
console.log("[7BTV Control Emotes Panel] Opening control panel...");
console.log("[7BTV Control Emotes Panel] Creating control panel...");
console.log("[7BTV Control Emotes Panel] Adding button...");
console.log("[7BTV Control Emotes Panel] Updating channel list...");
console.log("[7BTV Control Emotes Panel] Creating file input element...");
// Удаляем некорректные логи с event, так как они не в контексте события
console.log("[7BTV Control Emotes Panel] Processing imported channels...");
console.log("[7BTV Control Emotes Panel] Updating interface...");
console.log("[7BTV Control Emotes Panel] Showing all emotes in chat...");
console.log("[7BTV Control Emotes Panel] Blocking all emotes...");
console.log("[7BTV Control Emotes Panel] Hiding emotes for a channel...");
console.log(`%c[7BTV Control Emotes Panel] %cWaiting for chat container...`,
    'color:rgb(255, 114, 173); font-weight: bold;', // Стиль для [7BTV Control Emotes Panel]
    'color: rgb(255, 114, 173)  ;'); // Стиль для остального текста

console.log("[7BTV Control Emotes Panel] Creating context menu...");





// Добавляем переменные для отслеживания состояния
let lastKnownBlockedCount = blockedEmotes.length + blockedChannels.length;
let lastCheckTime = Date.now();
let isRestarting = false;

// Функция проверки состояния блокировки
function checkBlockingStatus() {
    console.log(`%c[WATCHDOG] %cПроверка состояния блокировки...`,
        'color:rgb(221, 101, 175); font-weight: bold;',
        'color: rgb(164, 207, 44) ;');

    const chatContainer = document.querySelector('.chat-scrollable-area__message-container');
    if (!chatContainer) {
        console.log(
            "%c[WATCHDOG]%c Контейнер чата не найден, перезапускаем наблюдение",
            'color:rgb(172, 147, 223); font-weight: bold;',
            'color: rgb(164, 207, 44) ;');
        observeChatContainer(); // Перезапускаем наблюдение
        return false;
    }

    const emotes = chatContainer.querySelectorAll('.chat-line__message img, .chat-line__message .emote, .chat-line__message .bttv-emote, .chat-line__message .seventv-emote');
    if (emotes.length === 0) {
        console.log("[WATCHDOG] Эмодзи в чате не найдены, пропускаем проверку");
        return true;
    }

    let failureDetected = false;

    emotes.forEach((emote, index) => {
        if (index > 5) return;
        const emoteId = emote.getAttribute('data-emote-id');
        const shouldBeBlocked = emoteId && (blockedChannels.some(e => e.id === emoteId) || blockedEmotes.some(e => e.id === emoteId));
        const isVisible = emote.style.display !== 'none';

        if (shouldBeBlocked && isVisible) {
            console.log(`[WATCHDOG] Обнаружен сбой: эмодзи с ID ${emoteId} должен быть скрыт, но виден!`);
            failureDetected = true;
        } else if (!shouldBeBlocked && !isVisible) {
            console.log(`[WATCHDOG] Обнаружен сбой: эмодзи с ID ${emoteId} не должен быть скрыт, но скрыт!`);
            failureDetected = true;
        }
    });

    const currentBlockedCount = blockedEmotes.length + blockedChannels.length;
    if (currentBlockedCount !== lastKnownBlockedCount) {
        console.log(
            `%c[WATCHDOG] %cКоличество заблокированных элементов изменилось: %c${lastKnownBlockedCount} -> ${currentBlockedCount}`,
            'color: rgb(221, 101, 175); font-weight: bold;',
            'color: rgb(164, 207, 44);',
            'color: rgb(255, 165, 0); font-weight: bold;'
        );
        lastKnownBlockedCount = currentBlockedCount;
    }

    return !failureDetected;
}

function showNotification(message, duration = 3000) {
    const notification = document.createElement('div');
    notification.innerText = message; // Добавляем текст
    notification.style.position = 'relative';
    notification.style.bottom = '99%';
    notification.style.maxWidth = '155px';
    notification.style.left = '61%';
    notification.style.backgroundColor = '#341d41';
    notification.style.color = ' #30aa54';
    notification.style.padding = '6px';
    notification.style.borderRadius = '40px';
    notification.style.boxShadow = 'rgb(130, 113, 148) 1px 1px 7px 4px';
    notification.style.zIndex = '1001';
    notification.style.fontSize = '10px';

    // Начальные стили для анимации (уменьшенный размер)
    notification.style.transform = 'scale(0)'; // Начинаем с масштаба 0
    notification.style.opacity = '0'; // Начинаем с прозрачности 0
    notification.style.transition = 'transform 0.3s ease, opacity 0.3s ease'; // Плавный переход для масштаба и прозрачности

    document.body.appendChild(notification);

    // Запускаем анимацию увеличения после добавления в DOM
    setTimeout(() => {
        notification.style.transform = 'scale(1)'; // Увеличиваем до нормального размера
        notification.style.opacity = '1'; // Делаем полностью видимым
    }, 10); // Небольшая задержка для запуска перехода

    // Удаляем уведомление после завершения длительности
    setTimeout(() => {
        // Добавляем анимацию исчезновения перед удалением (опционально)
        notification.style.transform = 'scale(0)';
        notification.style.opacity = '0';
        setTimeout(() => {
            notification.remove();
        }, 300); // Соответствует времени transition
    }, duration);
}

// Функция перезапуска логики блокировки
function restartBlockingLogic() {
    if (isRestarting) return;
    isRestarting = true;
   // Перезапуск логики - оранжевый цвет (в процессе)
          console.log(
            '%c[WATCHDOG]%c Перезапуск логики блокировки...',
            'color: #FF4500; font-weight: bold;', // Стиль для [WATCHDOG] (OrangeRed)
            'color: #FF4500;' // Стиль для остального текста
          );
    showNotification(" chat not found ... waiting... ", 3000); // уведомление о перезапуске когда сбой  failure

    observer.disconnect();
    const chatContainer = document.querySelector('.chat-scrollable-area__message-container');
    if (chatContainer) {
        const emotes = chatContainer.querySelectorAll('.chat-line__message img, .chat-line__message .emote, .chat-line__message .bttv-emote, .chat-line__message .seventv-emote');
        emotes.forEach(emote => {
            emote.style.display = '';
            emote.removeAttribute('data-emote-id');
        });
        observeChatContainer();
        toggleEmotesInNode(chatContainer);
    } else {
        observeChatContainer();
    }

    updateBlockedList();
    updateCounter();
    setTimeout(() => {
        isRestarting = false;
        // Перезапуск завершен - зеленый цвет (успех)
              console.log(
                '%c[WATCHDOG]%c Перезапуск завершен',
                'color: #00C4B4; font-weight: bold;', // Стиль для [WATCHDOG] (Teal)
                'color: #00C4B4;' // Стиль для остального текста
              );
    }, 1000); // Задержка для предотвращения спама
}

// Периодическая проверка состояния (watchdog)
function startWatchdog() {
    setInterval(() => {
        const currentTime = Date.now();
        if (currentTime - lastCheckTime < 5000) return; // Проверяем не чаще, чем раз в 5 секунд
        lastCheckTime = currentTime;

        const isWorking = checkBlockingStatus();
        if (!isWorking) {
            // Обнаружен сбой - желтый цвет (предупреждение)
                console.log(
                  '%c[WATCHDOG]%c Обнаружен сбой в работе блокировки, перезапуск...',
                  'color: #FFA500; font-weight: bold;', // Стиль для [WATCHDOG] (Orange)
                  'color: #FFA500;' // Стиль для остального текста
                );
            restartBlockingLogic();
        } else {
            console.log(`%c[WATCHDOG] %cБлокировка работает корректно!`,
                'color:rgb(6, 167, 0); font-weight: bold;',
                       'color: rgb(164, 207, 44) ;');
        }
    }, 10000); // Проверяем каждые 10 секунд
}


    //================  Модуль управления темами ================== //
    (function () {
        // Определяем начальный массив тем
        const defaultThemes = [
{
                name: 'default',
                displayName: 'Default Theme',
                styles: {chartModal: {
                        backgroundColor: 'rgba(0, 0, 0, 0.8)'
                    },
                    chartContainer: {
                        backgroundColor: ' #fff',
                        borderRadius: '8px'
                    },
                    closeChartButton: {
                        background: ' #944646',
                        color: ' #fff'
                    },
                    controlPanel: {
                        background: '-webkit-linear-gradient(270deg, hsla(50, 76%, 56%, 1) 0%, hsla(32, 83%, 49%, 1) 25%, hsla(0, 37%, 37%, 1) 59%, hsla(276, 47%, 24%, 1) 79%, hsla(261, 11%, 53%, 1) 100%)',
                        border: '1px solid #ccc',
                        boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
                        color: '#fff'
                    },
                    lastItemHighlight: {
                        backgroundColor: ' #ffd700' // Золотой полупрозрачный
                    },
                    openPanelButton: {
                        background: ' #4c2a5e', // Фиолетовый фон по умолчанию
                        color: ' #bda3d7',     // Светло-фиолетовый текст
                        border: 'none'
                    },
                    switchContainer: {
                        backgroundColor: ' #ccb8eb5c', // Полупрозрачный фон выключенного состояния
                        activeBackgroundColor: ' #bda3d7' // Фон включенного состояния
                    },
                    switchCircle: {
                        backgroundColor: ' #4c2a5e', // Фиолетовый кружок
                        boxShadow: '0 2px 6px rgba(0, 0, 0, 0.8)'
                    },
                    list: {
                        background: '-webkit-linear-gradient(45deg, hsla(292, 44%, 16%, 1) 0%, hsla(173, 29%, 48%, 1) 100%)',
                        border: '1px solid #ffffff',
                        color: '#fff',
                        scrollbarThumb: ' #C1A5EF',
                        scrollbarTrack: ' #455565'
                    },
                    counter: {
                        backgroundColor: ' #b69dcf',
                        color: ' #4c2a5e',
                        border: '3px solid #4c2a5e'
                    },
                    sortContainer: {
                        backgroundColor: 'rgb(89, 51, 114)',
                        border: '1px solid rgb(255, 255, 255)',
                        color: '#fff'
                    },
                    title: {
                        color: ' #2a1e38'
                    },
                    buttons: {
                        background: ' #907cad',
                        color: '#fff'
                    },
                    versionLabel: {
                        color: 'rgb(62, 33, 85)'
                    },
                    searchInput: {
                        background: '#192427',
                        color: ' #b69dcf',
                        border: '1px solid #b69dcf'
                    },
                    input: {
                        background: ' #192427',
                        color: ' #b69dcf',
                        border: '1px solid #b69dcf'
                    },
                    themeSelect: {
                        background: ' #192427',
                        color: ' #b69dcf',
                        border: '1px solid #c1a5ef'
                    },
                    platformSelect: {
                        background: ' #192427',
                        color: ' #b69dcf',
                        border: '1px solid #c1a5ef'
                    },
                    deleteButton: {
                        background: ' #944646',
                        color: ' #fff',
                        hoverBackground: 'linear-gradient(135deg, #480a0c 56%, #ca5d5f 98%, #8b4040 100%)'
                    },
                    listItemText: { // Название платформы и префикс (например, "7tv > BasedGod" и "(prefix: ...)")
                        color: ' #ffffff' // Белый текст для темного фона
                    },
                    listItemLink: { // Префикс как ссылка (например, "(prefix: ...)")
                        color: ' #b3e0f2' // Светло-голубой для ссылок
                    },

                    listItemDate: { // Дата (например, "15/03/2025, 22:30")
                        color: ' #cccccc' // Светло-серый для даты
                    }, // Added comma here
                    chartWrapper: {
                        backgroundColor: '#fff',
                        border: '1px solid #ffffff',
                        color: '#000'
                    }}
            },
            {
                name: 'dark',
                displayName: 'Dark Theme',
                styles: {
                    controlPanel: {
                        background: 'linear-gradient(282deg, #1a1a1a 0%, #848282 100%)',
                        border: '1px solid #444',
                        boxShadow: '0 4px 6px rgba(0, 0, 0, 0.5)',
                        color: '#ddd'
                    },
                    lastItemHighlight: {
                        backgroundColor: 'rgba(255, 217, 0, 0.47)' // Золотой полупрозрачный
                    },

                    openPanelButton: {
                        background: ' #84828266', // Темно-серый фон
                        color: ' #171c1c', // Темно-серый текст
                        border: 'none'
                    },
                    switchContainer: {
                        backgroundColor: ' #464646', // Темно-серый фон выключенного состояния
                        activeBackgroundColor: ' #7e7e7e' // Темно-серый фон включенного состояния
                    },
                    switchCircle: {
                        backgroundColor: ' #5d5d5d',      // Светло-серый кружок
                        boxShadow: '0 2px 6px #000000'
                    },
                    themeSelect: {
                        background: ' #2c2c2c',
                        color: ' #a8a8a8',
                        border: '1px solid #666'
                    },
                    list: {
                        background: 'linear-gradient(45deg, #301144, #196a6185, #56bfcdad)',
                        border: '1px solid #555',
                        color: '#ddd',
                        scrollbarThumb: '#666',
                        scrollbarTrack: '#222'
                    },
                    counter: {
                        backgroundColor: ' #333',
                        color: ' #9f9f9f',
                        border: '3px solid #9e9e9e'
                    },
                    sortContainer: {
                        backgroundColor: ' #333333',
                        border: '1px solid #555',
                        color: '#ddd'
                    },
                    title: {
                        color: ' #333333'
                    },
                    buttons: {
                        background: ' #444',
                        color: ' #ddd'
                    },
                    versionLabel: {
                        color: ' #333333'
                    },
                    searchInput: {
                        background: ' #444444 ',
                        color: ' #ddd',
                        border: '1px solid #555'
                    },
                    input: {
                        background: ' #444444',
                        color: ' #ddd',
                        border: '1px solid #555'
                    },
                    platformSelect: {
                        background: ' #2c2c2c',
                        color: ' #a8a8a8',
                        border: '1px solid #666'
                    },
                    deleteButton: {
                        background: ' #444444',
                        color: '#ddd',
                        hoverBackground: 'linear-gradient(135deg, rgb(78, 64, 64) 0%, rgb(99, 86, 86) 56%, rgb(58, 51, 51) 98%, rgb(37, 37, 37) 100%)'
                    },
                    listItemText: { // Название платформы и префикс
                        color: ' #dddddd' // Светло-серый для контраста
                    },
                    listItemLink: { // Префикс как ссылка
                        color: ' #99ccff' // Светло-синий для ссылок
                    },
                    listItemDate: { // Дата
                        color: ' #bbbbbb' // Средне-серый для даты
                    }
                }
            },
            {
                name: 'light',
                displayName: 'Light Theme',
                styles: {
                    controlPanel: {
                        background: '-webkit-linear-gradient(270deg, #a694b1 ,  #f0f0f0 0%,  rgb(121, 121, 121) 100%)',
                        border: '1px solid #999',
                        boxShadow: '0 4px 6px rgba(0, 0, 0, 0.2)',
                        color: ' #000000'
                    },
                    lastItemHighlight: {
                        backgroundColor: 'rgba(255, 217, 0, 0.56)' // Золотой полупрозрачный
                    },
                    openPanelButton: {
                        background: ' #828282',   // Светло-серый фон
                        color: ' #333',        // Темно-серый текст
                        border: '1px solid #999'
                    },
                    switchContainer: {
                        backgroundColor: ' #171c1c',      // Светло-серый фон выключенного состояния
                        activeBackgroundColor: ' #464646' // Серый фон включенного состояния
                    },
                    switchCircle: {
                        backgroundColor: '#666',      // Средне-серый кружок
                        boxShadow: '0 2px 6px rgba(0, 0, 0, 0.3)'
                    },
                    themeSelect: {
                        background: 'rgb(172, 172, 172)',
                        color: ' #050505',
                        border: '1px solid #999'
                    },
                    list: {
                        background: 'linear-gradient(45deg, #a694b1 , rgba(218, 144, 178, 0.46),rgb(70, 182, 197))',
                        border: '1px solid #ccc',
                        color: ' #000000',
                        scrollbarThumb: '#aaa',
                        scrollbarTrack: '#ddd'
                    },
                    counter: {
                        backgroundColor: ' #e0e0e0',
                        color: ' #000000',
                        border: '3px solid #999'
                    },
                    sortContainer: {
                        backgroundColor: ' #acacac',
                        border: '1px solid #ccc',
                        color: ' #000000'
                    },
                    title: {
                        color: ' #000000'
                    },
                    buttons: {
                        background: '#bbb',
                        color: ' #000000'
                    },
                    versionLabel: {
                        color: ' #000000'
                    },
                    searchInput: {
                        background: ' #acacac',
                        color: ' #000000',
                        border: '1px solid #ccc'
                    },
                    input: {
                        background: ' #acacac',
                        color: 'rgba(0, 0, 0, 0.2)',
                        border: '1px solid #ccc'
                    },
                    platformSelect: {
                        background: 'rgb(172, 172, 172)',
                        color: ' #050505',
                        border: '1px solid #999'
                    },
                    deleteButton: {
                        background: '#ff9999',
                        color: 'rgb(43, 37, 37)',
                        hoverBackground: 'linear-gradient(135deg, rgb(110, 109, 109) 0%, rgb(107, 90, 90) 56%, rgb(177, 154, 154) 98%, rgb(172, 141, 141) 100%)'
                    },
                    listItemText: { // Название платформы и префикс
                        color: 'rgb(0, 53, 24)' // Тёмно-зелёный для читаемости
                    },
                    listItemLink: { // Префикс как ссылка
                        color: 'rgb(51, 134, 120)' // Бирюзовый для ссылок
                    },
                    listItemDate: { // Дата
                        color: ' #555555' // Серый для даты
                    }
                }
            },
            {
                name: 'waterBlue',
                displayName: 'Water Blue Theme',
                styles: {
                    controlPanel: {
                        background: '-webkit-linear-gradient(90deg, rgb(0, 23, 89) 0%, rgb(18 105 99) 100%)',
                        border: '1px solid #2a69ac',
                        boxShadow: '0 4px 8px #1a3a8a',
                        color: ' #e0f2fa'
                    },
                    lastItemHighlight: {
                        backgroundColor: 'rgba(255, 217, 0, 0.6)' // Золотой полупрозрачный
                    },
                    openPanelButton: {
                        background: ' #3d8eb9', // Голубой фон
                        color: ' #09415e',      // Темно-голубой текст
                        border: '1px solid #2a69ac'
                    },
                    switchContainer: {
                        backgroundColor: ' #2a69ac',   // Темно-голубой фон выключенного состояния
                        activeBackgroundColor: ' #09415e' // Светло-голубой фон включенного состояния
                    },
                    switchCircle: {
                        backgroundColor: ' #3d8eb9',   // светло-синий кружок
                        boxShadow: '0 2px 6px rgba(26, 58, 138, 0.5)'
                    },
                    themeSelect: {
                        background: ' #2a69ac',
                        color: 'rgb(206, 220, 226)',
                        border: '1px solid #4fb3c8'
                    },
                    list: {
                        background: 'linear-gradient(45deg,rgb(21, 45, 112) 0%,rgb(82, 169, 172)',
                        border: '1px solid #2a69ac',
                        color: 'rgb(182, 202, 211)',
                        scrollbarThumb: ' #4fb3c8',
                        scrollbarTrack: ' #2a69ac'
                    },
                    counter: {
                        backgroundColor: ' #3d8eb9',
                        color: ' #011d59',
                        border: '3px solid #011d59'
                    },
                    sortContainer: {
                        backgroundColor: ' #042251',
                        border: '1px solid #4fb3c8',
                        color: ' #e0f2fa'
                    },
                    title: {
                        color: ' #4fc8b9'
                    },
                    buttons: {
                        background: ' #3d8eb9',
                        color: ' #011d59'
                    },
                    versionLabel: {
                        color: ' #b3e0f2'
                    },
                    searchInput: {
                        background: ' #2a69ac',
                        color: ' #e0f2fa',
                        border: '1px solid #4fb3c8'
                    },
                    input: {
                        background: ' #2a69ac',
                        color: ' #e0f2fa',
                        border: '1px solid #4fb3c8'
                    },
                    platformSelect: {
                        background: ' #2a69ac',
                        color: ' #e0f2fa',
                        border: '1px solid #4fb3c8'
                    },
                    deleteButton: {
                        background: ' #022258',
                        color: ' #e0f2fa',
                        hoverBackground: 'linear-gradient(135deg, rgb(64, 124, 255) 0%, rgb(0, 3, 179) 56%, rgb(64, 93, 255) 98%, rgb(107, 154, 255) 100%)'
                    },
                    listItemText: { // Название платформы и префикс
                        color: ' #e0f2fa' // Светло-голубой для контраста
                    },
                    listItemLink: { // Префикс как ссылка
                        color: ' #b3e0f2' // Ещё более светлый голубой для ссылок
                    },
                    listItemDate: { // Дата
                        color: ' #c0e0f0' // Нежно-голубой для даты
                    }
                }
            },
            {
                name: 'black-raspberry',
                displayName: 'Black Raspberry Theme',
                styles: {
                    controlPanel: {
                        background: ' #1a1a1a', // Глубокий чёрный фон
                        border: '1px solid #333', // Тёмно-серая граница
                        boxShadow: '0 4px 6px rgba(0, 0, 0, 0.7)', // Более глубокая тень
                        color: ' #db7093' // Малиновый текст для контраста
                    },
                    lastItemHighlight: {
                        backgroundColor: 'rgba(199, 21, 133, 0.3)' // Полупрозрачный малиновый для подсветки
                    },
                    openPanelButton: {
                        background: ' #000000', // Чёрный фон
                        color: ' #c71585', // Малиновый текст
                        border: 'none'
                    },
                    switchContainer: {
                        backgroundColor: ' #333333', // Тёмно-серый фон выключенного состояния
                        activeBackgroundColor: ' #c71585' // Малиновый фон включенного состояния
                    },
                    switchCircle: {
                        backgroundColor: ' #222222', // Светло-малиновый кружок
                        boxShadow: ' #000000c9 0px 3px 8px 2px'
                    },
                    themeSelect: {
                        background: ' #1a1a1a', // Чёрный фон
                        color: ' #db7093', // Малиновый текст
                        border: '1px solid #444'
                    },
                    list: {
                        background: 'linear-gradient(45deg, #0f0615, #94225d)', // Чёрно малиновый градиент для списка
                        border: '1px solid #444', // Тёмно-серая граница
                        color: ' #db7093', // Малиновый текст
                        scrollbarThumb: ' #c71585', // Малиновый ползунок
                        scrollbarTrack: ' #222222' // Чёрный трек
                    },
                    counter: {
                        backgroundColor: ' #000000', // Чёрный фон
                        color: ' #db7093', // Малиновый текст
                        border: '3px solid #c71585' // Малиновая граница
                    },
                    sortContainer: {
                        backgroundColor: ' #1a1a1a', // Чёрный фон
                        border: '1px solid #444', // Тёмно-серая граница
                        color: ' #db7093' // Малиновый текст
                    },
                    title: {
                        color: ' #c71585' // Малиновый заголовок
                    },
                    buttons: {
                        background: ' #333333', // Тёмно-серый фон кнопок
                        color: ' #db7093' // Малиновый текст
                    },
                    versionLabel: {
                        color: ' #c71585' // Малиновый текст
                    },
                    searchInput: {
                        background: ' #1a1a1a', // Чёрный фон
                        color: ' #db7093', // Малиновый текст
                        border: '1px solid #c71585' // Малиновая граница
                    },
                    input: {
                        background: '#1a1a1a', // Чёрный фон
                        color: '#db7093', // Малиновый текст
                        border: '1px solid #c71585' // Малиновая граница
                    },
                    platformSelect: {
                        background: '#1a1a1a', // Чёрный фон
                        color: '#db7093', // Малиновый текст
                        border: '1px solid #444'
                    },
                    deleteButton: {
                        background: ' #333333', // Тёмно-серый фон
                        color: ' #b76780', // темно серый текст
                        hoverBackground: 'linear-gradient(135deg, #a44c83 0%, #6b293e 56%, #8a4e6f 98%)' // Градиент с малиновыми оттенками
                    },
                    listItemText: { // Название платформы и префикс
                        color: ' #db7093' // Малиновый текст для контраста
                    },
                    listItemLink: { // Префикс как ссылка
                        color: ' #ff69b4' // Более светлый малиновый для ссылок
                    },
                    listItemDate: { // Дата
                        color: ' #888888' // Серый для даты, чтобы не отвлекать
                    }
                }
            },
            {
                name: 'deepSeaTurquoise',
                displayName: 'Deep Sea Turquoise Theme',
                styles: {
                    controlPanel: {
                        background: 'linear-gradient(180deg,rgb(23, 86, 87),rgb(70, 171, 129), #6ec2c5 )',
                        border: '1px solid #2a8c8e',
                        boxShadow: '0 4px 8px rgba(23, 94, 95, 0.52)',
                        color: ' #d1f1f2'
                    },
                    lastItemHighlight: {
                        backgroundColor: 'rgba(255, 217, 0, 0.55)' // Золотой полупрозрачный
                    },
                    openPanelButton: {
                        background: ' #2a8c8e', // Бирюзовый фон
                        color: ' #1b4746',      // Светло-бирюзовый текст
                        border: '1px solid #155557'
                    },
                    switchContainer: {
                        backgroundColor: ' #155557',   // Темно-бирюзовый фон выключенного состояния
                        activeBackgroundColor: ' #1b4746' // Светло-бирюзовый фон включенного состояния
                    },
                    switchCircle: {
                        backgroundColor: ' #2a8c8e',   // Темно-бирюзовый кружок
                        boxShadow: '0 2px 6px rgba(23, 94, 95, 0.5)'
                    },
                    themeSelect: {
                        background: ' #155557',
                        color: ' #d1f1f2',
                        border: '1px solid #46a8ab'
                        },
                    list: {
                        background: 'linear-gradient(45deg,  #1d6f71 ,rgb(105, 26, 151)',
                        border: '1px solid #2a8c8e',
                        color: ' #d1f1f2',
                        scrollbarThumb: ' #46a8ab',
                        scrollbarTrack: ' #0c3a3c'
                    },
                    counter: {
                        backgroundColor: ' #2a8c8e',
                        color: ' #0c3a3c',
                        border: '3px solid #0c3a3c'
                    },
                    sortContainer: {
                        backgroundColor: ' #1b4746',
                        border: '1px solid #46a8ab',
                        color: ' #67beb8'
                    },
                    title: {
                        color: ' #3fa3a5'
                    },
                    buttons: {
                        background: ' #2a8c8e',
                        color: ' #0c3a3c'
                    },
                    versionLabel: {
                        color: ' #61d0d2'
                    },
                    searchInput: {
                        background: ' #155557',
                        color: ' #d1f1f2',
                        border: '1px solid #46a8ab'
                    },
                    input: {
                        background: ' #155557',
                        color: ' #d1f1f2',
                        border: '1px solid #46a8ab'
                    },
                    platformSelect: {
                        background: 'rgb(58, 92, 94)',
                        color: ' #d1f1f2',
                        border: '1px solidrgb(177, 78, 202)'
                    },
                    deleteButton: {
                        background: ' #16332c',
                        color: ' #367e72',
                        hoverBackground: 'linear-gradient(135deg, #1b5e44 52%, #367e72 59%)'
                    },
                    listItemText: { // Название платформы и префикс
                        color: ' #d1f1f2' // Светло-бирюзовый для контраста
                    },
                    listItemLink: { // Префикс как ссылка
                        color: ' #a3d9db' // Более мягкий бирюзовый для ссылок
                    },
                    listItemDate: { // Дата
                        color: ' #b0e0e2' // Нежный бирюзовый для даты
                    }
                }
            },
    {
    name: 'glassmorphism-ios',
    displayName: 'Glassmorphism iOS',
    styles: {
        controlPanel: {
            background: 'rgba(255, 255, 255, 0.1)',
            backdropFilter: 'blur(10px)',
            WebkitBackdropFilter: 'blur(10px)',
            border: '1px solid rgba(255, 255, 255, 0.2)',
            boxShadow: '0 8px 32px rgba(0, 0, 0, 0.15)',
            borderRadius: '16px',
            color: '#ffffff'
        },
        lastItemHighlight: {
            backgroundColor: 'rgba(255, 255, 255, 0.3)'
        },
        openPanelButton: {
            background: 'rgba(255, 255, 255, 0.15)',
            backdropFilter: 'blur(8px)',
            WebkitBackdropFilter: 'blur(8px)',
            color: '#ffffff',
            border: 'none',
            borderRadius: '12px'
        },
        switchContainer: {
            backgroundColor: 'rgba(255, 255, 255, 0.1)',
            activeBackgroundColor: 'rgba(18, 148, 253, 0.36)',
            backdropFilter: 'blur(6px)',
            WebkitBackdropFilter: 'blur(6px)',
            borderRadius: '15px'
        },
        switchCircle: {
            backgroundColor: 'rgba(255, 255, 255, 0.9)',
            boxShadow: '0 2px 6px rgba(0, 0, 0, 0.2)',
            borderRadius: '50%'
        },
        themeSelect: {
            background: ' #63636342',
            backdropFilter: 'blur(8px)',
            WebkitBackdropFilter: 'blur(8px)',
            color: 'rgb(0, 0, 0)',
            border: '1px solid rgba(255, 255, 255, 0.2)',
            borderRadius: '10px'
        },
        list: {
            background: 'rgba(255, 255, 255, 0.1)',
            backdropFilter: 'blur(10px)',
            WebkitBackdropFilter: 'blur(10px)',
            border: '1px solid rgba(255, 255, 255, 0.2)',
            color: '#ffffff',
            scrollbarThumb: 'rgba(255, 255, 255, 0.5)',
            scrollbarTrack: 'rgba(255, 255, 255, 0.05)',
            borderRadius: '12px'
        },
        counter: {
            backgroundColor: 'rgba(255, 255, 255, 0.2)',
            backdropFilter: 'blur(6px)',
            WebkitBackdropFilter: 'blur(6px)',
            color: '#ffffff',
            border: '1px solid rgba(255, 255, 255, 0.3)',
            borderRadius: '8px'
        },
        sortContainer: {
            backgroundColor: 'rgba(255, 255, 255, 0.15)',
            backdropFilter: 'blur(8px)',
            WebkitBackdropFilter: 'blur(8px)',
            border: '1px solid rgba(255, 255, 255, 0.2)',
            color: '#ffffff',
            borderRadius: '10px'
        },
        title: {
            color: '#ffffff'
        },
        buttons: {
            background: 'rgba(255, 255, 255, 0.15)',
            backdropFilter: 'blur(8px)',
            WebkitBackdropFilter: 'blur(8px)',
            color: '#ffffff',
            borderRadius: '10px'
        },
        versionLabel: {
            color: 'rgba(255, 255, 255, 0.8)'
        },
        searchInput: {
            background: 'rgba(255, 255, 255, 0.15)',
            backdropFilter: 'blur(8px)',
            WebkitBackdropFilter: 'blur(8px)',
            color: '#ffffff',
            border: '1px solid rgba(255, 255, 255, 0.2)',
            borderRadius: '10px'
        },
        input: {
            background: 'rgba(255, 255, 255, 0.15)',
            backdropFilter: 'blur(8px)',
            WebkitBackdropFilter: 'blur(8px)',
            color: ' #ffffff',
            border: '1px solid rgba(255, 255, 255, 0.2)',
            borderRadius: '10px'
        },
        platformSelect: {
            background: ' #63636342 ',
            backdropFilter: 'blur(8px)',
            WebkitBackdropFilter: 'blur(8px)',
            color: 'rgb(0, 0, 0)',
            border: '1px solid rgba(255, 255, 255, 0.2)',
            borderRadius: '10px'
        },
        deleteButton: {
            background: 'rgba(255, 19, 19, 0.2)',
            backdropFilter: 'blur(8px)',
            WebkitBackdropFilter: 'blur(8px)',
            color: ' #ffffff',
            hoverBackground: 'linear-gradient(135deg, rgba(255, 75, 75, 0.3) 0%, rgba(200, 50, 50, 0.5) 100%)',
            borderRadius: '8px'
        },
        listItemText: {
            color: ' #ffffff'
        },
        listItemLink: {
            color: 'rgba(0, 122, 255, 0.9)'
        },
        listItemDate: {
            color: 'rgba(255, 255, 255, 0.7)'
        }
    }
}
];

    // Загружаем темы из хранилища или используем дефолтные
    let themes = GM_getValue('themes', defaultThemes);
    let selectedThemeName = GM_getValue('selectedTheme', 'default');

    // Функция для сохранения тем в хранилище
    function saveThemes() {
        GM_setValue('themes', themes);
        console.log('[7BTV Control Emotes Panel] Темы сохранены в хранилище:', themes);
    }

    // Функция для сохранения выбранной темы
    function saveSelectedTheme(themeName) {
        selectedThemeName = themeName;
        GM_setValue('selectedTheme', themeName);
        console.log('[7BTV Control Emotes Panel] Выбранная тема сохранена:', themeName);
    }

    // Функция для применения темы
    function applyTheme(themeName) {
        const theme = themes.find(t => t.name === themeName) || themes[0];
        if (!theme) {
            console.warn(`[7BTV Control Emotes Panel] Тема ${themeName} не найдена, используется 'default'`);
            applyTheme('default');
            return;
        }

        console.log(`[7BTV Control Emotes Panel] Применение темы: ${themeName}`);

        const currentPanelDisplay = controlPanel.style.display;
        const currentPanelHeight = controlPanel.style.height;

        if (openPanelButton) {
            Object.assign(openPanelButton.style, theme.styles.openPanelButton);
            openPanelButton.style.position = 'fixed';
            openPanelButton.style.zIndex = '10000';
            openPanelButton.style.transition = 'background 0.3s ease';
        }

        if (switchContainer) {
            Object.assign(switchContainer.style, {
                backgroundColor: isPanelOpen ? theme.styles.switchContainer.activeBackgroundColor : theme.styles.switchContainer.backgroundColor,
                width: '44px',
                height: '27px',
                borderRadius: '13px',
                position: 'relative',
                transition: 'background 0.3s ease'
            });
        }

        if (switchCircle) {
            Object.assign(switchCircle.style, theme.styles.switchCircle);
            switchCircle.style.width = '19px';
            switchCircle.style.height = '19px';
            switchCircle.style.borderRadius = '50%';
            switchCircle.style.position = 'absolute';
            switchCircle.style.top = '3px';
            switchCircle.style.left = '3px';
            switchCircle.style.transition = 'transform 0.3s ease';
        }

        if (controlPanel) {
            Object.assign(controlPanel.style, theme.styles.controlPanel);
            controlPanel.style.display = currentPanelDisplay;
            controlPanel.style.height = currentPanelHeight;
            controlPanel.style.transition = 'height 0.3s ease';
        }

        if (list) {
            Object.assign(list.style, theme.styles.list);
            const styleElement = document.getElementById('customScrollbarStyle') || document.createElement('style');
            styleElement.id = 'customScrollbarStyle';
            styleElement.innerHTML = `
                #blockedList::-webkit-scrollbar { width: 25px; }
                #blockedList::-webkit-scrollbar-thumb {
                    background-color: ${theme.styles.list.scrollbarThumb};
                    border-radius: 8px;
                    border: 3px solid #4F3E6A;
                    height: 80px;
                }
                #blockedList::-webkit-scrollbar-thumb:hover { background-color: ${theme.styles.list.scrollbarThumb}; }
                #blockedList::-webkit-scrollbar-thumb:active { background-color: ${theme.styles.list.scrollbarThumb}; }
                #blockedList::-webkit-scrollbar-track {
                    background: ${theme.styles.list.scrollbarTrack};
                    border-radius: 0px 0px 8px 0px;
                }
                #blockedList::-webkit-scrollbar-track:hover { background: ${theme.styles.list.scrollbarTrack}; }
                #blockedList::-webkit-scrollbar-track:active { background: ${theme.styles.list.scrollbarTrack}; }
            `;
            if (!document.getElementById('customScrollbarStyle')) {
                document.head.appendChild(styleElement);
            }
        }

        const lastItemHighlightStyle = document.createElement('style');
        lastItemHighlightStyle.id = 'lastItemHighlightStyle';
        lastItemHighlightStyle.innerHTML = `
            .last-item-highlight {
                background-color: ${theme.styles.lastItemHighlight?.backgroundColor || ' #ffd700'};
                transition: background-color 0.5s ease;
            }
        `;
        const existingStyle = document.getElementById('lastItemHighlightStyle');
        if (existingStyle) {
            existingStyle.remove();
        }
        document.head.appendChild(lastItemHighlightStyle);

        if (counter) {
            Object.assign(counter.style, theme.styles.counter);
            counter.style.display = 'flex';
        }

        if (sortContainer) {
            Object.assign(sortContainer.style, theme.styles.sortContainer);
            sortContainer.style.display = 'flex';
        }

        if (title) {
            Object.assign(title.style, theme.styles.title);
            title.style.display = 'block';
        }

        const buttons = [addButton, clearAllButton, exportButton, importButton, unblockAllButton, blockAllButton, searchButton];
        buttons.forEach(button => {
            Object.assign(button.style, theme.styles.buttons);
            button.onmouseover = () => {
                button.style.background = '-webkit-linear-gradient(135deg, #443157 0%, rgb(90, 69, 122) 56%, #443157 98%, #443157 100%)';
            };
            button.onmouseout = () => {
                button.style.background = theme.styles.buttons.background;
            };
        });

        if (versionLabel) {
            Object.assign(versionLabel.style, theme.styles.versionLabel);
        }

        if (searchInput) {
            Object.assign(searchInput.style, theme.styles.searchInput);
        }

        if (input) {
            Object.assign(input.style, theme.styles.input);
        }

        if (platformSelect) {
            Object.assign(platformSelect.style, theme.styles.platformSelect);
        }

        if (themeSelect) {
            Object.assign(themeSelect.style, theme.styles.themeSelect);
        }

            // Обновляем стили кнопок Delete и сохраняем их в currentDeleteButtonStyles
    const deleteButtons = list.querySelectorAll('.delete-button');
    deleteButtons.forEach(button => {
        Object.assign(button.style, theme.styles.deleteButton, {
            height: '35px',
            width: '75px',
            fontWeight: 'bold',
            fontSize: '16px',
            border: 'none',
            borderRadius: '4px',
            cursor: 'pointer',
            boxShadow: '0 4px 8px rgba(0, 0, 0, 0.6)',
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            transition: 'background 0.3s ease'
        });
        button.onmouseover = () => {
            button.style.background = theme.styles.deleteButton.hoverBackground;
        };
        button.onmouseout = () => {
            button.style.background = theme.styles.deleteButton.background;
        };
    });

    // Сохраняем текущие стили кнопки Delete
    currentDeleteButtonStyles = {
        background: theme.styles.deleteButton.background,
        color: theme.styles.deleteButton.color,
        hoverBackground: theme.styles.deleteButton.hoverBackground
    };
    console.log('[7BTV Control Emotes Panel] Сохранены стили кнопки Delete:', currentDeleteButtonStyles);


        if (list) {
            const listItemTexts = list.querySelectorAll('.list-item-text');
            const listItemLinks = list.querySelectorAll('.list-item-link');
            const listItemDates = list.querySelectorAll('.list-item-date');
            listItemTexts.forEach(span => {
                Object.assign(span.style, theme.styles.listItemText);
            });
            listItemLinks.forEach(span => {
                Object.assign(span.style, theme.styles.listItemLink);
            });
            listItemDates.forEach(span => {
                Object.assign(span.style, theme.styles.listItemDate);
            });
        }

        saveSelectedTheme(themeName);
    }



  // ============== Создаём интерфейс для выбора темы ========================== //
    const themeSelectorContainer = document.createElement('div');
    themeSelectorContainer.style.position = 'relative';
    themeSelectorContainer.style.bottom = '100px';
    themeSelectorContainer.style.width = '126px';
    themeSelectorContainer.style.left = '0px';
    themeSelectorContainer.style.zIndex = '10001';

    const themeSelect = document.createElement('select');
    themeSelect.style.padding = '5px';
    themeSelect.style.height = '35px';
    themeSelect.style.width = '126px';
    themeSelect.style.borderRadius = '4px';
    themeSelect.style.background = ' #192427';
    themeSelect.style.color = ' #b69dcf';
    themeSelect.style.border = '1px solid #b69dcf';

    themes.forEach(theme => {
        const option = document.createElement('option');
        option.value = theme.name;
        option.innerText = theme.displayName;
        if (theme.name === selectedThemeName) {
            option.selected = true;
        }
        themeSelect.appendChild(option);
    });

    themeSelect.onchange = () => {
        const selectedTheme = themeSelect.value;
        applyTheme(selectedTheme);
    };

    themeSelectorContainer.appendChild(themeSelect);
    controlPanel.appendChild(themeSelectorContainer);

    // Применяем сохранённую тему при загрузке
    applyTheme(selectedThemeName);
})();

// Запускаем watchdog
startWatchdog();


})();