package com.grigowashere.aismap.controllers;

import android.content.Context;
import android.util.Log;
import com.grigowashere.aismap.models.Vessel;
import com.grigowashere.aismap.models.AISVessel;
import com.grigowashere.aismap.controllers.NMEAParser;
import com.grigowashere.aismap.controllers.AndroidNMEAListener;
import com.grigowashere.aismap.controllers.GPSLocationListener;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Контроллер для обработки NMEA сообщений
 * Отвечает только за парсинг и обработку NMEA данных
 */
public class NMEAController implements 
    NMEAParser.NMEAParserListener,
    AndroidNMEAListener.NMEAMessageCallback,
    GPSLocationListener.LocationCallback {
    
    private static final String TAG = "NMEAController";
    
    private Context context;
    private NMEAParser nmeaParser;
    private AndroidNMEAListener androidNmeaListener;
    private GPSLocationListener gpsLocationListener;
    private ExecutorService executor;
    
    // Callbacks для уведомления других компонентов
    private NMEAControllerListener listener;
    
    // Текущий режим работы
    private String currentDataMode = "hybrid";
    
    // Диагностика
    private long lastServiceLogTime = 0;
    
    public interface NMEAControllerListener {
        void onVesselUpdated(Vessel vessel);
        void onDOPUpdated(double pdop, double hdop, double vdop);
        void onAISVesselUpdated(AISVessel vessel);
        void onNavigationAidUpdated(com.grigowashere.aismap.models.AISNavigationAid navigationAid);
        void onParseError(String error);
        void onGPSLocationUpdated(Vessel vessel);
    }
    
    public NMEAController(Context context) {
        this.context = context;
        this.executor = Executors.newCachedThreadPool();
        initializeParser();
    }
    
    /**
     * Инициализирует NMEA парсер
     */
    private void initializeParser() {
        // Инициализация парсера NMEA
        nmeaParser = new NMEAParser();
        nmeaParser.setListener(this);
        
        // Инициализация GPS Location Listener (для координат)
        gpsLocationListener = new GPSLocationListener(context);
        gpsLocationListener.setCallback(this);
        
        // Инициализация Android NMEA слушателя (для курса, скорости, DOP)
        androidNmeaListener = new AndroidNMEAListener(context);
        androidNmeaListener.setCallback(this);
        
        Log.i(TAG, "NMEA Controller инициализирован");
    }
    
    /**
     * Настраивает режим работы на основе настроек
     */
    private void configureMode(String dataMode) {
        this.currentDataMode = dataMode;
        Log.i(TAG, "Настройка режима: " + dataMode);
        
        if ("hybrid".equals(dataMode)) {
            // Гибридный режим: GPS для координат, NMEA для остального
            nmeaParser.setGPSLocationListener(gpsLocationListener);
            nmeaParser.setHybridMode(true);
            Log.i(TAG, "Гибридный режим: GPS координаты + NMEA данные");
        } else if ("android_only".equals(dataMode)) {
            // Только Android GPS - не используем NMEA парсер
            nmeaParser.setGPSLocationListener(null);
            nmeaParser.setHybridMode(false);
            Log.i(TAG, "Режим Android GPS: только встроенный GPS");
        } else if ("nmea_only".equals(dataMode)) {
            // Только NMEA - игнорируем GPS Location Manager
            nmeaParser.setGPSLocationListener(null);
            nmeaParser.setHybridMode(false);
            Log.i(TAG, "Режим NMEA: только внешний NMEA");
        } else {
            // По умолчанию гибридный режим
            nmeaParser.setGPSLocationListener(gpsLocationListener);
            nmeaParser.setHybridMode(true);
            Log.i(TAG, "Режим по умолчанию: гибридный");
        }
    }
    
    /**
     * Устанавливает слушателя для уведомлений
     */
    public void setListener(NMEAControllerListener listener) {
        this.listener = listener;
    }
    
    /**
     * Запускает Android NMEA слушатель
     */
    public void startAndroidNMEAListener() {
        if (androidNmeaListener != null && !androidNmeaListener.isListening()) {
            Log.i(TAG, "🚀 Запускаем Android NMEA слушатель...");
            boolean success = androidNmeaListener.startListening();
            if (success) {
                Log.i(TAG, "✅ Android NMEA слушатель успешно запущен");
            } else {
                Log.e(TAG, "❌ Не удалось запустить Android NMEA слушатель");
            }
        }
    }
    
    /**
     * Останавливает Android NMEA слушатель
     */
    public void stopAndroidNMEAListener() {
        if (androidNmeaListener != null && androidNmeaListener.isListening()) {
            Log.i(TAG, "⏹️ Останавливаем Android NMEA слушатель...");
            androidNmeaListener.stopListening();
        }
    }
    
    /**
     * Запускает GPS Location слушатель
     */
    public void startGPSLocationListener() {
        if (gpsLocationListener != null && !gpsLocationListener.isListening()) {
            Log.i(TAG, "🚀 Запускаем GPS Location слушатель...");
            boolean success = gpsLocationListener.startListening();
            if (success) {
                Log.i(TAG, "✅ GPS Location слушатель успешно запущен");
            } else {
                Log.e(TAG, "❌ Не удалось запустить GPS Location слушатель");
            }
        }
    }
    
    /**
     * Останавливает GPS Location слушатель
     */
    public void stopGPSLocationListener() {
        if (gpsLocationListener != null && gpsLocationListener.isListening()) {
            Log.i(TAG, "⏹️ Останавливаем GPS Location слушатель...");
            gpsLocationListener.stopListening();
        }
    }
    
    /**
     * Парсит NMEA сообщение
     */
    public void parseNMEAMessage(String message) {
        // Фильтруем сообщения в зависимости от режима
        if ("android_only".equals(currentDataMode)) {
            // В режиме только Android GPS игнорируем GPS NMEA сообщения, но пропускаем AIS
            if (isGPSNMEAMessage(message)) {
                Log.d(TAG, "Игнорируем GPS NMEA сообщение в режиме android_only: " + message.substring(0, Math.min(20, message.length())));
                return;
            }
            // AIS сообщения (!) пропускаем всегда
        }
        
        if (executor != null && !executor.isShutdown()) {
            try {
                executor.execute(() -> {
                    try {
                        nmeaParser.parseNMEA(message);
                        // Диагностика: логируем каждые 10 секунд
                        long now = System.currentTimeMillis();
                        if (now - lastServiceLogTime > 10000) {
                            Log.d(TAG, "✅ NMEA сообщение обработано в фоновом потоке");
                            lastServiceLogTime = now;
                        }
                    } catch (Exception e) {
                        Log.e(TAG, "❌ Ошибка парсинга NMEA в фоновом потоке: " + e.getMessage(), e);
                        if (listener != null) {
                            listener.onParseError(e.getMessage());
                        }
                    }
                });
            } catch (java.util.concurrent.RejectedExecutionException e) {
                Log.w(TAG, "Thread pool is shutting down, skipping NMEA processing: " + e.getMessage());
            }
        } else {
            Log.w(TAG, "Thread pool is not available, skipping NMEA processing");
        }
    }
    
    /**
     * Проверяет, является ли сообщение GPS NMEA (а не AIS)
     */
    private boolean isGPSNMEAMessage(String message) {
        if (message == null || message.length() < 6) {
            return false;
        }
        
        // AIS сообщения начинаются с "!" - их всегда пропускаем
        if (message.startsWith("!")) {
            return false;
        }
        
        // GPS NMEA сообщения начинаются с "$" - их фильтруем в режиме android_only
        if (message.startsWith("$")) {
            return true;
        }
        
        // Остальные сообщения пропускаем
        return false;
    }
    
    /**
     * Устанавливает режим работы с данными
     */
    public void setDataMode(String mode) {
        String oldMode = currentDataMode;
        configureMode(mode);
        
        // Если режим изменился, перезапускаем слушатели
        if (!oldMode.equals(mode)) {
            Log.i(TAG, "Режим изменился с " + oldMode + " на " + mode + ", перезапускаем слушатели");
            restartListeners();
        }
    }
    
    /**
     * Перезапускает слушатели на основе текущего режима
     */
    private void restartListeners() {
        Log.i(TAG, "🔄 Перезапускаем слушатели в режиме: " + currentDataMode);
        
        // Останавливаем все слушатели
        stopAndroidNMEAListener();
        stopGPSLocationListener();
        
        // Запускаем нужные слушатели в зависимости от режима
        if ("hybrid".equals(currentDataMode)) {
            Log.i(TAG, "📍 Гибридный режим: Android GPS + NMEA");
            startAndroidNMEAListener();
            startGPSLocationListener();
        } else if ("android_only".equals(currentDataMode)) {
            Log.i(TAG, "📍 Режим Android GPS: только встроенный GPS");
            startGPSLocationListener();
        } else if ("nmea_only".equals(currentDataMode)) {
            Log.i(TAG, "📍 Режим NMEA: только внешний NMEA");
            startAndroidNMEAListener();
        } else {
            Log.i(TAG, "📍 Режим по умолчанию: гибридный");
            startAndroidNMEAListener();
            startGPSLocationListener();
        }
        
        Log.i(TAG, "✅ Слушатели перезапущены");
    }
    
    /**
     * Получает GPS Location Listener для внешнего использования
     */
    public GPSLocationListener getGPSLocationListener() {
        return gpsLocationListener;
    }
    
    /**
     * Проверяет, включен ли Android NMEA слушатель
     */
    public boolean isAndroidNMEAListenerActive() {
        return androidNmeaListener != null && androidNmeaListener.isListening();
    }
    
    /**
     * Проверяет, включен ли GPS Location слушатель
     */
    public boolean isGPSLocationListenerActive() {
        return gpsLocationListener != null && gpsLocationListener.isListening();
    }
    
    // Реализация NMEAParserListener
    
    @Override
    public void onVesselUpdated(Vessel vessel) {
        if (listener != null) {
            listener.onVesselUpdated(vessel);
        }
    }
    
    @Override
    public void onDOPUpdated(double pdop, double hdop, double vdop) {
        if (listener != null) {
            listener.onDOPUpdated(pdop, hdop, vdop);
        }
    }
    
    @Override
    public void onAISVesselUpdated(AISVessel vessel) {
        if (listener != null) {
            listener.onAISVesselUpdated(vessel);
        }
    }
    
    @Override
    public void onNavigationAidUpdated(com.grigowashere.aismap.models.AISNavigationAid navigationAid) {
        if (listener != null) {
            listener.onNavigationAidUpdated(navigationAid);
        }
    }
    
    @Override
    public void onParseError(String error) {
        Log.e(TAG, "Ошибка парсинга NMEA: " + error);
        if (listener != null) {
            listener.onParseError(error);
        }
    }
    
    // Реализация NMEAMessageCallback
    
    @Override
    public void onNMEAMessage(String message, long timestamp) {
        // Диагностика: логируем каждые 10 секунд
        long now = System.currentTimeMillis();
        if (now - lastServiceLogTime > 10000) {
            Log.d(TAG, "📱 Android NMEA сообщение получено");
            lastServiceLogTime = now;
        }
        
        // Парсим полученные данные как NMEA В ФОНОВОМ ПОТОКЕ
        parseNMEAMessage(message);
    }
    
    @Override
    public void onGPSStatusChanged(int status) {
        Log.i(TAG, "GPS статус изменился: " + status);
    }
    
    // Реализация GPSLocationListener.LocationCallback
    @Override
    public void onLocationUpdated(Vessel vessel) {
        // Игнорируем обновления от GPS, если режим только NMEA
        if ("nmea_only".equals(currentDataMode)) {
            Log.d(TAG, "Игнорируем GPS обновление в режиме nmea_only");
            return;
        }
        if (listener != null) {
            listener.onGPSLocationUpdated(vessel);
        }
    }

    @Override
    public void onError(String error) {
        Log.e(TAG, "Ошибка Android NMEA: " + error);
        if (listener != null) {
            listener.onParseError(error);
        }
    }
    
    /**
     * Освобождает ресурсы
     */
    public void cleanup() {
        stopAndroidNMEAListener();
        stopGPSLocationListener();
        
        if (androidNmeaListener != null) {
            androidNmeaListener.cleanup();
        }
        
        if (gpsLocationListener != null) {
            gpsLocationListener.cleanup();
        }
        
        if (executor != null && !executor.isShutdown()) {
            executor.shutdown();
            try {
                // Ждем завершения всех задач максимум 2 секунды
                if (!executor.awaitTermination(2, java.util.concurrent.TimeUnit.SECONDS)) {
                    Log.w(TAG, "Thread pool did not terminate gracefully, forcing shutdown");
                    executor.shutdownNow();
                }
            } catch (InterruptedException e) {
                Log.w(TAG, "Thread pool shutdown interrupted: " + e.getMessage());
                executor.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
        
        Log.i(TAG, "NMEA Controller очищен");
    }
}
