package com.grigowashere.aismap.controllers;

import android.content.Context;
import android.util.Log;
import com.grigowashere.aismap.controllers.UDPListener;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Контроллер для сетевых операций
 * Отвечает только за UDP слушание и отправку данных
 */
public class NetworkController implements UDPListener.UDPListenerCallback {
    
    private static final String TAG = "NetworkController";
    
    private Context context;
    private UDPListener udpListener;
    private ExecutorService executor;
    
    // Настройки сети
    private int udpPort = 10110; // Стандартный порт для AIS
    private boolean isUDPEnabled = false;
    private boolean isUDPNMEAEnabled = false;
    
    // Callbacks для уведомления других компонентов
    private NetworkControllerListener listener;
    
    // Диагностика
    private long lastServiceLogTime = 0;
    
    public interface NetworkControllerListener {
        void onDataReceived(String data, String sourceAddress, int sourcePort);
        void onUDPError(String error);
    }
    
    public NetworkController(Context context) {
        this.context = context;
        this.executor = Executors.newCachedThreadPool();
        initializeUDPListener();
    }
    
    /**
     * Инициализирует UDP слушатель
     */
    private void initializeUDPListener() {
        udpListener = new UDPListener(udpPort);
        udpListener.setCallback(this);
        Log.i(TAG, "Network Controller инициализирован с портом: " + udpPort);
    }
    
    /**
     * Устанавливает слушателя для уведомлений
     */
    public void setListener(NetworkControllerListener listener) {
        this.listener = listener;
    }
    
    /**
     * Включает/выключает UDP слушатель
     */
    public void setUDPEnabled(boolean enabled) {
        this.isUDPEnabled = enabled;
        if (enabled && !udpListener.isRunning()) {
            startUDPListener();
        } else if (!enabled && udpListener.isRunning()) {
            stopUDPListener();
        }
        Log.i(TAG, "UDP слушатель: " + (enabled ? "включен" : "выключен"));
    }
    
    /**
     * Запускает UDP слушатель
     */
    public void startUDPListener() {
        if (isUDPEnabled && executor != null && !executor.isShutdown()) {
            try {
                executor.execute(() -> {
                    udpListener.start();
                    Log.i(TAG, "UDP слушатель запущен на порту: " + udpPort);
                });
            } catch (java.util.concurrent.RejectedExecutionException e) {
                Log.w(TAG, "Thread pool is shutting down, cannot start UDP listener: " + e.getMessage());
            }
        }
    }
    
    /**
     * Останавливает UDP слушатель
     */
    public void stopUDPListener() {
        if (udpListener.isRunning()) {
            executor.execute(() -> {
                udpListener.stop();
                Log.i(TAG, "UDP слушатель остановлен");
            });
        }
    }
    
    /**
     * Отправляет данные по UDP
     */
    public void sendUDPData(String data, String address, int port) {
        if (udpListener != null) {
            udpListener.sendData(data, address, port);
        }
    }
    
    /**
     * Устанавливает UDP порт
     */
    public void setUDPPort(int port) {
        if (port < 1 || port > 65535) {
            Log.w(TAG, "Некорректный UDP порт: " + port);
            return;
        }
        
        this.udpPort = port;
        Log.i(TAG, "UDP порт установлен: " + port);
        
        // Если UDP слушатель уже создан, нужно будет его пересоздать
        if (udpListener != null && udpListener.getPort() != port) {
            Log.i(TAG, "UDP порт изменен, потребуется перезапуск UDP слушателя");
            restartUDPListener();
        }
    }
    
    /**
     * Перезапускает UDP слушатель с новым портом
     */
    public void restartUDPListener() {
        if (udpListener != null) {
            Log.i(TAG, "Перезапускаем UDP слушатель с портом: " + udpPort);
            
            // Останавливаем текущий слушатель
            udpListener.stop();
            udpListener.cleanup();
            
            // Создаем новый слушатель с новым портом
            udpListener = new UDPListener(udpPort);
            udpListener.setCallback(this);
            
            // Запускаем, если UDP включен
            if (isUDPEnabled) {
                startUDPListener();
                Log.i(TAG, "UDP слушатель перезапущен на порту: " + udpPort);
            }
        }
    }
    
    /**
     * Включает/выключает UDP NMEA
     */
    public void setUDPNMEAEnabled(boolean enabled) {
        this.isUDPNMEAEnabled = enabled;
        Log.i(TAG, "UDP NMEA: " + (enabled ? "включен" : "выключен"));
    }
    
    /**
     * Проверяет, включен ли UDP слушатель
     */
    public boolean isUDPEnabled() {
        return isUDPEnabled;
    }
    
    /**
     * Проверяет, включен ли UDP NMEA
     */
    public boolean isUDPNMEAEnabled() {
        return isUDPNMEAEnabled;
    }
    
    /**
     * Получает текущий UDP порт
     */
    public int getUDPPort() {
        return udpPort;
    }
    
    /**
     * Получает статус сетевых настроек
     */
    public String getNetworkStatus() {
        return String.format(
            "UDP: порт=%d, включен=%s, NMEA=%s",
            udpPort,
            isUDPEnabled ? "да" : "нет",
            isUDPNMEAEnabled ? "включен" : "выключен"
        );
    }
    
    // Реализация UDPListenerCallback
    
    @Override
    public void onDataReceived(String data, String sourceAddress, int sourcePort) {
        // Диагностика: логируем каждые 10 секунд
        long now = System.currentTimeMillis();
        if (now - lastServiceLogTime > 10000) {
            Log.d(TAG, "📡 UDP данные получены от " + sourceAddress + ":" + sourcePort);
            lastServiceLogTime = now;
        }
        
        // Передаем данные слушателю
        if (listener != null) {
            listener.onDataReceived(data, sourceAddress, sourcePort);
        }
    }
    
    @Override
    public void onUDPError(String error) {
        Log.e(TAG, "UDP ошибка: " + error);
        if (listener != null) {
            listener.onUDPError(error);
        }
    }
    
    /**
     * Освобождает ресурсы
     */
    public void cleanup() {
        stopUDPListener();
        
        if (udpListener != null) {
            udpListener.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, "Network Controller очищен");
    }
}
