const path = require('path');
const { exec } = require('child_process');
const { Worker } = require('worker_threads');
const os = require('os');
const EventEmitter = require('events');
const WebSocketClient = require('websocket').client;
const { handleMethod } = require('./metods');
const { initWiFiCheck } = require('./checkWi-Fi');
const { startMavenServer } = require('./mavenServer');
const { checkAndInstallDependencies } = require('./deploy');
const config = require('./configs/config_neuro-air.json')

class neuroAirClient extends EventEmitter {
    constructor(ventilator) {
        super();
        this.holoFan = ventilator;
        this.config = config;
        this.webSocketClient = new WebSocketClient();
        this.interval = null;
        this.idlePlaylist = null;
        this.stationNumbers = [];
        this.currentStationIndex = 0;

        // Инициализация таймеров
        this.checkWiFiCapabilityTimer = null;
        this.connectToWiFiTimer = null;

        this.holoFan.awaitHoloFanTimeout = null;
        this.holoFan.needConnect = true;
        this.holoFan.connected = false;
        // this.holoFan = ventilator;
        this.holoFan.statusWiFI = false // статус доступности Wi-Fi
        this.holoFan.connectedWiFi = false // статус подключения к голографическому вентилятору по Wi-Fi
        this.holoFan.mavenServerStart = false // статус запуска maven сервера

        this.holoFan.deviceState = null // чтение состояний устройства
        this.holoFan.filePlayLists = null // cписок плейлистов
        this.holoFan.videoList = null // список видеофайлов
        this.holoFan.currentListName = null // имя текущего плейлиста
        this.holoFan.CurrentVideoName = null // имя текущего видеофайла

        //Здесь вся инициализация по запуску пакета
        setTimeout(() => {
            checkAndInstallDependencies(this, this.holoFan);
        }, 1500);
        
        // Запускаем проверку Wi-Fi с задержкой в 2 секунды
        setTimeout(() => {
            initWiFiCheck(this, this.holoFan, this.config);
        }, 2000);

    }
    connectToHoloFan() {
        // Здесь вся инициализация перед подключением к голографическому вентилятору
            this.connect();
    }

    async connect() {
        try {
            await startMavenServer(this.holoFan, this.emit.bind(this)); // Запуск сервера с SDK
            this.emit('data', 'Сервер успешно запущен');
            this.holoFan.mavenServerStart = true;

            this.webSocketClient.on('connectFailed', (error) => {
                this.emit('error', 'Ошибка подключения: ' + error.toString());
                
                // Устанавливаем таймер для повторной попытки подключения
                setTimeout(() => {
                    this.connect().catch(console.error);
                }, this.config.retryInterval_connectIndex * 1000); // Задержка перед повторной попыткой подключения
            });

            this.webSocketClient.on('connect', (client) => {
                this.emit('connected', 'Клиент WebSocket подключен');
                this.holoFan.connected = true;

                client.on('error', (error) => {
                    this.emit('error', 'Ошибка подключения: ' + error.toString());
                });

                client.on('close', () => {
                    this.emit('disconnected', 'Соединение WebSocket закрыто');
                    this.holoFan.connected = false;
                    clearInterval(this.interval);

                    if (this.retryConnectionTimeout) {
                        clearTimeout(this.retryConnectionTimeout);
                    }

                    this.retryConnectionTimeout = setTimeout(() => {
                        this.connect().catch(console.error);
                    }, this.config.retryInterval_connectIndex * 1000); // Повторное подключение через 15 секунд
                });

                // Переменная для хранения предыдущего списка плейлистов
                let previousPlaylists = [];

                client.on('message', async (message) => {
                    const event = { data: message.utf8Data };
                
                    if (event.data.startsWith("{\"method\":\"playlistItems\"")) {
                        const parsedData = JSON.parse(event.data);
                        const playlistItems = parsedData.videoList.map(video => video.fileName);
                        const playlistIndex = this.currentPlaylistIndex;
                        const playlistName = this.currentPlaylistName;
                        if (playlistName) {
                            this.holoFan.playlists[playlistName] = playlistItems;
                        }
                    } else if (event.data.startsWith("fileList:")) {
                        const rawData = event.data.substring(9);
                        let files = [];
                        if (rawData.includes(';')) {
                            files = rawData.split(';').filter(file => file.endsWith('.mp4'));
                        } else {
                            files = rawData.split(',').filter(file => file.endsWith('.mp4'));
                        }
                        this.holoFan.videoList = files;
                        this.emit('data', `Это общий список файлов с устройства: ${files}`);
                
                    } else if (event.data.startsWith("playList:")) {
                        const playLists = event.data.substring(9).split(';');
                
                        // Сравниваем новый список плейлистов с предыдущим
                        if (JSON.stringify(playLists) !== JSON.stringify(previousPlaylists)) {
                            previousPlaylists = playLists; // Обновляем предыдущий список плейлистов
                
                            this.holoFan.filePlayLists = playLists;
                            this.holoFan.playlists = playLists.reduce((acc, playlist) => {
                                acc[playlist] = [];
                                return acc;
                            }, {});
                            // this.emit('message', `Это плейлисты: ${this.holoFan.filePlayLists}`);
                            await this.loadPlaylistsWithVideos(playLists);
                        } 
                
                    } else if (event.data.toLowerCase().startsWith("currentplaylist:")) {
                        const prefixLength = "currentplaylist:".length;
                        const rawData = event.data.substring(prefixLength).trim();
                        const playlistIndexStr = rawData.trim();
                        const playlistIndex = parseInt(playlistIndexStr, 10);
                
                        if (!isNaN(playlistIndex)) {
                            this.holoFan.currentListName = playlistIndex;
                            // this.emit('message', `Это плейлист, который играет сейчас: ${this.holoFan.currentListName}`);
                        } 
                    } else if (event.data.startsWith("currentVideo:")) {
                        let currentVideoData = event.data.substring(13).split(';');
                        let currentVideoIndex = parseInt(currentVideoData[0]);
                        this.holoFan.CurrentVideoName = currentVideoData[1];
                        // this.emit('message', `Это название видео, играющего сейчас: ${this.holoFan.CurrentVideoName}`);
                    } else if (event.data.startsWith("uploadSuccess")) {
                        this.sendCommand('readFileList');
                    } else if (event.data.startsWith("deviceState:")) {
                        const deviceStateData = event.data.substring(12);
                        try {
                            this.holoFan.deviceState = JSON.parse(deviceStateData);
                            this.emit('data', `Состояние устройства обновлено: ${JSON.stringify(this.holoFan.deviceState)}`);
                        } catch (error) {
                            this.emit('error', "Ошибка при разборе данных о состоянии устройства: " + error)
                        }
                    }
                });
                
                this.webSocket = client;

                // Вызов калибровки после подключения
                handleMethod(this, { methodName: 'calibrate', holoFan: this.holoFan, config: this.config,  args: { calibrate: this.holoFan, indexIdlePlayList: this.config.indexIdlePlayList } });
            });

            this.webSocketClient.connect(`ws://${this.holoFan.host}:${this.holoFan.port}/ws`);
        } catch (error) {
            this.emit('error', 'Ошибка запуска сервера: ' + error.toString());
            this.holoFan.mavenServerStart = false;

            if (this.retryConnectionTimeout) {
                clearTimeout(this.retryConnectionTimeout);
            }

            this.retryConnectionTimeout = setTimeout(() => {
                this.connect().catch(console.error);
            }, this.config.retryInterval_connectIndex * 1000); // Повторная попытка через 15 секунд
        }
    }

    callCommand(command, data = {}) {
        if (this.holoFan.connected) {
            handleMethod(this, {methodName: command, holoFan: this.holoFan, config: this.config, args: data} );
        }
    }
    
    // Функция для загрузки плейлистов с видео
    async loadPlaylistsWithVideos(playLists) {
        for (const [index, playlistName] of playLists.entries()) {
            await new Promise((resolve) => {
                const handler = (message) => {
                    const event = { data: message.utf8Data };
                    if (event.data.startsWith("{\"method\":\"playlistItems\"")) {
                        const parsedData = JSON.parse(event.data);
                        const playlistItems = parsedData.videoList.map(video => video.fileName);
                        // console.log(`Добавление видео в плейлист '${playlistName}': ${playlistItems}`);
                        this.holoFan.playlists[playlistName] = playlistItems;
                        this.webSocket.off('message', handler);
                        resolve();
                    }
                };
                this.currentPlaylistIndex = index;
                this.currentPlaylistName = playlistName;
                this.webSocket.on('message', handler);
                // console.log(`Отправка команды для чтения элементов плейлиста '${playlistName}' (индекс ${index})`);
                this.sendCommand('readPlayListItems', index);
            });
        }
        // this.emit('message', `Полный список плейлистов с видео: ${JSON.stringify(this.holoFan.playlists)}`);
    }

    sendCommand(method, args = {}) {
        try {
            const command = {
                method: method,
                args: typeof args === 'string' ? args : JSON.stringify(args)
            };
            const jsonCommand = JSON.stringify(command);
            // console.log("Отправка команды: ", jsonCommand); // Логирование команды перед отправкой
            this.webSocket.send(jsonCommand);
        } catch (error) {
            this.emit('error', `Ошибка при отправке команды ${method}: ${error.message}`);
        }
    }
}

module.exports = neuroAirClient;