package com.grigowashere.aismap.utils;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

/**
 * Менеджер настроек приложения
 * Управляет сохранением и загрузкой настроек в SharedPreferences
 */
public class SettingsManager {
    
    private static final String TAG = "SettingsManager";
    private static final String PREFS_NAME = "AISMapSettings";
    
    // Ключи для настроек
    private static final String KEY_UDP_PORT = "udp_port";
    private static final String KEY_UDP_ENABLED = "udp_enabled";
    private static final String KEY_ANDROID_NMEA_ENABLED = "android_nmea_enabled";
    private static final String KEY_UDP_NMEA_ENABLED = "udp_nmea_enabled";
    private static final String KEY_DATA_MODE = "data_mode";
    // Источник координат собственного судна. Отделён от KEY_DATA_MODE,
    // так как начиная с BLE v2 ais_hub сам поставляет ownship по BLE,
    // а настройки выше трактуют только старый NMEA-тракт.
    private static final String KEY_GPS_SOURCE = "gps_source";
    private static final String KEY_DATA_STALE_WARNING_MINUTES = "data_stale_warning_minutes";
    private static final String KEY_DATA_STALE_REMOVE_MINUTES = "data_stale_remove_minutes";
    private static final String KEY_PATH_TRACKING_ENABLED = "path_tracking_enabled";
    private static final String KEY_PATH_COLOR = "path_color";
    private static final String KEY_PREDICTION_COLOR = "prediction_color";
    private static final String KEY_PATH_WIDTH = "path_width";
    private static final String KEY_PREDICTION_WIDTH = "prediction_width";
    private static final String KEY_PATH_MAX_POINTS = "path_max_points";
    private static final String KEY_PREDICTION_HORIZON_SEC = "prediction_horizon_sec";
    private static final String KEY_VIBRATION_ENABLED = "vibration_enabled";
    private static final String KEY_SOUND_ENABLED = "sound_enabled";
    private static final String KEY_KEEP_SCREEN_ON_ENABLED = "keep_screen_on_enabled";
    private static final String KEY_CURSOR_ENABLED = "cursor_enabled";
    private static final String KEY_NOTIFICATIONS_ENABLED = "notifications_enabled";
    private static final String KEY_DEBUG_ENABLED = "debug_enabled";
    private static final String KEY_SEAMARKS_ENABLED = "seamarks_enabled";
    private static final String KEY_ANDROID_GPS_ENABLED = "android_gps_enabled";
    // Map startup behavior
    private static final String KEY_START_CENTER_ON_LAST = "start_center_on_last";
    private static final String KEY_START_ZOOM_LEVEL = "start_zoom_level";
    /** Как карта следует за ориентацией: {@link #MAP_ROTATION_COMPASS} / COURSE / MANUAL */
    private static final String KEY_MAP_ROTATION_MODE = "map_rotation_mode";
    // BLE/NMEA settings
    private static final String KEY_BLE_ENABLED = "ble_enabled";
    private static final String KEY_BLE_DEVICE_MAC = "ble_device_mac";
    private static final String KEY_BLE_UDP_BRIDGE_ENABLED = "ble_udp_bridge_enabled";
    private static final String KEY_BLE_UDP_BRIDGE_HOST = "ble_udp_bridge_host";
    private static final String KEY_BLE_UDP_BRIDGE_PORT = "ble_udp_bridge_port";
    
    // Значения по умолчанию
    private static final int DEFAULT_UDP_PORT = 10110;
    private static final boolean DEFAULT_UDP_ENABLED = true;
    private static final boolean DEFAULT_ANDROID_NMEA_ENABLED = true;
    private static final boolean DEFAULT_UDP_NMEA_ENABLED = true;
    private static final String DEFAULT_DATA_MODE = "hybrid";
    private static final int DEFAULT_DATA_STALE_WARNING_MINUTES = 5; // Показывать losingtarget.xml
    private static final int DEFAULT_DATA_STALE_REMOVE_MINUTES = 7; // Удалять из списка
    private static final boolean DEFAULT_PATH_TRACKING_ENABLED = true;
    private static final int DEFAULT_PATH_COLOR = 0xFF00FFFF; // Голубой
    private static final int DEFAULT_PREDICTION_COLOR = 0xFFFFFF00; // Желтый
    private static final float DEFAULT_PATH_WIDTH = 3.0f;
    private static final float DEFAULT_PREDICTION_WIDTH = 2.0f;
    private static final int DEFAULT_PATH_MAX_POINTS = 100; // Уменьшено с 300 до 100 для предотвращения зависаний
    private static final int DEFAULT_PREDICTION_HORIZON_SEC = 60;
    private static final boolean DEFAULT_VIBRATION_ENABLED = true;
    private static final boolean DEFAULT_SOUND_ENABLED = true;
    private static final boolean DEFAULT_KEEP_SCREEN_ON_ENABLED = true;
    private static final boolean DEFAULT_CURSOR_ENABLED = false;
    private static final boolean DEFAULT_NOTIFICATIONS_ENABLED = true;
    private static final boolean DEFAULT_ANDROID_GPS_ENABLED = true;
    private static final boolean DEFAULT_DEBUG_ENABLED = false;
    private static final boolean DEFAULT_SEAMARKS_ENABLED = false;
    // Map startup defaults
    private static final boolean DEFAULT_START_CENTER_ON_LAST = true;
    private static final float DEFAULT_START_ZOOM_LEVEL = 14.0f;
    // BLE defaults
    private static final boolean DEFAULT_BLE_ENABLED = false;
    private static final String DEFAULT_BLE_DEVICE_MAC = "";
    private static final boolean DEFAULT_BLE_UDP_BRIDGE_ENABLED = false;
    private static final String DEFAULT_BLE_UDP_BRIDGE_HOST = "255.255.255.255";
    private static final int DEFAULT_BLE_UDP_BRIDGE_PORT = 10110;
    
    // Режимы работы с данными
    public static final String DATA_MODE_HYBRID = "hybrid";
    public static final String DATA_MODE_NMEA_ONLY = "nmea_only";
    public static final String DATA_MODE_ANDROID_ONLY = "android_only";

    // Источник координат собственного судна.
    // - GPS_SOURCE_HUB: позиция берётся из ais_hub (BLE ownship.update).
    //   Android GPS/NMEA слушать не нужно. AIS-цели всегда идут через BLE.
    // - GPS_SOURCE_ANDROID: позиция берётся из Android Location API
    //   (+ опциональный внешний NMEA по UDP). BLE может оставаться включённым
    //   ради AIS-целей, но его ownship.update игнорируется.
    public static final String GPS_SOURCE_HUB = "ble_hub";
    public static final String GPS_SOURCE_ANDROID = "android";
    private static final String DEFAULT_GPS_SOURCE = GPS_SOURCE_HUB;

    /** Север вверх; поворот двумя пальцами, авто-не вмешивается. */
    public static final String MAP_ROTATION_MANUAL = "manual";
    /** Как магнитный компас / азимут корпуса. */
    public static final String MAP_ROTATION_COMPASS = "compass";
    /** Как курс (COG / GPS bearing). */
    public static final String MAP_ROTATION_COURSE = "course";
    private static final String DEFAULT_MAP_ROTATION_MODE = MAP_ROTATION_MANUAL;
    
    private Context context;
    private SharedPreferences prefs;
    
    public SettingsManager(Context context) {
        this.context = context;
        this.prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
    }
    
    /**
     * Получает UDP порт
     */
    public int getUDPPort() {
        return prefs.getInt(KEY_UDP_PORT, DEFAULT_UDP_PORT);
    }
    
    /**
     * Устанавливает UDP порт
     */
    public void setUDPPort(int port) {
        if (port < 1 || port > 65535) {
            Log.w(TAG, "Некорректный порт: " + port + ", используем значение по умолчанию");
            port = DEFAULT_UDP_PORT;
        }
        prefs.edit().putInt(KEY_UDP_PORT, port).apply();
        Log.i(TAG, "UDP порт установлен: " + port);
    }
    
    /**
     * Проверяет, включен ли UDP слушатель
     */
    public boolean isUDPEnabled() {
        return prefs.getBoolean(KEY_UDP_ENABLED, DEFAULT_UDP_ENABLED);
    }
    
    /**
     * Включает/выключает UDP слушатель
     */
    public void setUDPEnabled(boolean enabled) {
        prefs.edit().putBoolean(KEY_UDP_ENABLED, enabled).apply();
        Log.i(TAG, "UDP слушатель: " + (enabled ? "включен" : "выключен"));
    }
    
    /**
     * Проверяет, включен ли Android NMEA
     */
    public boolean isAndroidNMEAEnabled() {
        return prefs.getBoolean(KEY_ANDROID_NMEA_ENABLED, DEFAULT_ANDROID_NMEA_ENABLED);
    }
    
    /**
     * Включает/выключает Android NMEA
     */
    public void setAndroidNMEAEnabled(boolean enabled) {
        prefs.edit().putBoolean(KEY_ANDROID_NMEA_ENABLED, enabled).apply();
        Log.i(TAG, "Android NMEA: " + (enabled ? "включен" : "выключен"));
    }
    
    /**
     * Проверяет, включен ли UDP NMEA
     */
    public boolean isUDPNMEAEnabled() {
        return prefs.getBoolean(KEY_UDP_NMEA_ENABLED, DEFAULT_UDP_NMEA_ENABLED);
    }
    
    /**
     * Включает/выключает UDP NMEA
     */
    public void setUDPNMEAEnabled(boolean enabled) {
        prefs.edit().putBoolean(KEY_UDP_NMEA_ENABLED, enabled).apply();
        Log.i(TAG, "UDP NMEA: " + (enabled ? "включен" : "выключен"));
    }
    
    /**
     * Получает режим работы с данными
     */
    public String getDataMode() {
        return prefs.getString(KEY_DATA_MODE, DEFAULT_DATA_MODE);
    }
    
    /**
     * Устанавливает режим работы с данными
     */
    public void setDataMode(String mode) {
        if (!isValidDataMode(mode)) {
            Log.w(TAG, "Некорректный режим данных: " + mode + ", используем значение по умолчанию");
            mode = DEFAULT_DATA_MODE;
        }
        prefs.edit().putString(KEY_DATA_MODE, mode).apply();
        Log.i(TAG, "Режим данных установлен: " + mode);
    }
    
    /**
     * Проверяет корректность режима данных
     */
    private boolean isValidDataMode(String mode) {
        return DATA_MODE_HYBRID.equals(mode) || 
               DATA_MODE_NMEA_ONLY.equals(mode) || 
               DATA_MODE_ANDROID_ONLY.equals(mode);
    }
    
    /**
     * Проверяет, включен ли гибридный режим
     */
    public boolean isHybridMode() {
        return DATA_MODE_HYBRID.equals(getDataMode());
    }
    
    /**
     * Проверяет, включен ли режим только NMEA
     */
    public boolean isNMEAOnlyMode() {
        return DATA_MODE_NMEA_ONLY.equals(getDataMode());
    }
    
    /**
     * Проверяет, включен ли режим только Android GPS
     */
    public boolean isAndroidOnlyMode() {
        return DATA_MODE_ANDROID_ONLY.equals(getDataMode());
    }
    
    /**
     * Текущий источник координат собственного судна: {@link #GPS_SOURCE_HUB}
     * или {@link #GPS_SOURCE_ANDROID}. По умолчанию — HUB.
     */
    public String getGpsSource() {
        String v = prefs.getString(KEY_GPS_SOURCE, DEFAULT_GPS_SOURCE);
        if (!GPS_SOURCE_HUB.equals(v) && !GPS_SOURCE_ANDROID.equals(v)) {
            return DEFAULT_GPS_SOURCE;
        }
        return v;
    }

    public void setGpsSource(String source) {
        if (!GPS_SOURCE_HUB.equals(source) && !GPS_SOURCE_ANDROID.equals(source)) {
            source = DEFAULT_GPS_SOURCE;
        }
        prefs.edit().putString(KEY_GPS_SOURCE, source).apply();
        Log.i(TAG, "GPS source: " + source);
    }

    public boolean isGpsFromHub() { return GPS_SOURCE_HUB.equals(getGpsSource()); }
    public boolean isGpsFromAndroid() { return GPS_SOURCE_ANDROID.equals(getGpsSource()); }

    /**
     * Переключает источник координат и возвращает новое значение.
     */
    public String toggleGpsSource() {
        String next = isGpsFromHub() ? GPS_SOURCE_ANDROID : GPS_SOURCE_HUB;
        setGpsSource(next);
        return next;
    }

    /**
     * Проверяет, включен ли Android GPS (Location API)
     */
    public boolean isAndroidGPSEnabled() {
        return prefs.getBoolean(KEY_ANDROID_GPS_ENABLED, DEFAULT_ANDROID_GPS_ENABLED);
    }
    
    /**
     * Включает/выключает Android GPS (Location API)
     */
    public void setAndroidGPSEnabled(boolean enabled) {
        prefs.edit().putBoolean(KEY_ANDROID_GPS_ENABLED, enabled).apply();
        Log.i(TAG, "Android GPS: " + (enabled ? "включен" : "выключен"));
    }

    // ===== BLE settings =====
    public boolean isBLEEnabled() {
        return prefs.getBoolean(KEY_BLE_ENABLED, DEFAULT_BLE_ENABLED);
    }

    public void setBLEEnabled(boolean enabled) {
        prefs.edit().putBoolean(KEY_BLE_ENABLED, enabled).apply();
        Log.i(TAG, "BLE: " + (enabled ? "включен" : "выключен"));
    }

    public String getBLEDeviceMac() {
        return prefs.getString(KEY_BLE_DEVICE_MAC, DEFAULT_BLE_DEVICE_MAC);
    }

    public void setBLEDeviceMac(String mac) {
        if (mac == null) mac = "";
        prefs.edit().putString(KEY_BLE_DEVICE_MAC, mac).apply();
        Log.i(TAG, "BLE MAC сохранён: " + mac);
    }

    public boolean isBleUdpBridgeEnabled() {
        return prefs.getBoolean(KEY_BLE_UDP_BRIDGE_ENABLED, DEFAULT_BLE_UDP_BRIDGE_ENABLED);
    }

    public void setBleUdpBridgeEnabled(boolean enabled) {
        prefs.edit().putBoolean(KEY_BLE_UDP_BRIDGE_ENABLED, enabled).apply();
        Log.i(TAG, "BLE UDP-bridge: " + (enabled ? "включен" : "выключен"));
    }

    public String getBleUdpBridgeHost() {
        return prefs.getString(KEY_BLE_UDP_BRIDGE_HOST, DEFAULT_BLE_UDP_BRIDGE_HOST);
    }

    public void setBleUdpBridgeHost(String host) {
        if (host == null || host.trim().isEmpty()) host = DEFAULT_BLE_UDP_BRIDGE_HOST;
        prefs.edit().putString(KEY_BLE_UDP_BRIDGE_HOST, host).apply();
        Log.i(TAG, "BLE UDP-bridge host: " + host);
    }

    public int getBleUdpBridgePort() {
        return prefs.getInt(KEY_BLE_UDP_BRIDGE_PORT, DEFAULT_BLE_UDP_BRIDGE_PORT);
    }

    public void setBleUdpBridgePort(int port) {
        if (port < 1 || port > 65535) port = DEFAULT_BLE_UDP_BRIDGE_PORT;
        prefs.edit().putInt(KEY_BLE_UDP_BRIDGE_PORT, port).apply();
        Log.i(TAG, "BLE UDP-bridge port: " + port);
    }
    
    /**
     * Сбрасывает все настройки к значениям по умолчанию
     */
    public void resetToDefaults() {
        prefs.edit()
            .putInt(KEY_UDP_PORT, DEFAULT_UDP_PORT)
            .putBoolean(KEY_UDP_ENABLED, DEFAULT_UDP_ENABLED)
            .putBoolean(KEY_ANDROID_NMEA_ENABLED, DEFAULT_ANDROID_NMEA_ENABLED)
            .putBoolean(KEY_UDP_NMEA_ENABLED, DEFAULT_UDP_NMEA_ENABLED)
            .putString(KEY_DATA_MODE, DEFAULT_DATA_MODE)
            .putInt(KEY_DATA_STALE_WARNING_MINUTES, DEFAULT_DATA_STALE_WARNING_MINUTES)
            .putInt(KEY_DATA_STALE_REMOVE_MINUTES, DEFAULT_DATA_STALE_REMOVE_MINUTES)
            .putBoolean(KEY_VIBRATION_ENABLED, DEFAULT_VIBRATION_ENABLED)
            .putBoolean(KEY_SOUND_ENABLED, DEFAULT_SOUND_ENABLED)
            .putBoolean(KEY_KEEP_SCREEN_ON_ENABLED, DEFAULT_KEEP_SCREEN_ON_ENABLED)
            .putBoolean(KEY_START_CENTER_ON_LAST, DEFAULT_START_CENTER_ON_LAST)
            .putFloat(KEY_START_ZOOM_LEVEL, DEFAULT_START_ZOOM_LEVEL)
            .putString(KEY_MAP_ROTATION_MODE, DEFAULT_MAP_ROTATION_MODE)
            .putBoolean(KEY_BLE_ENABLED, DEFAULT_BLE_ENABLED)
            .putString(KEY_BLE_DEVICE_MAC, DEFAULT_BLE_DEVICE_MAC)
            .putBoolean(KEY_BLE_UDP_BRIDGE_ENABLED, DEFAULT_BLE_UDP_BRIDGE_ENABLED)
            .putString(KEY_BLE_UDP_BRIDGE_HOST, DEFAULT_BLE_UDP_BRIDGE_HOST)
            .putInt(KEY_BLE_UDP_BRIDGE_PORT, DEFAULT_BLE_UDP_BRIDGE_PORT)
            .apply();
        Log.i(TAG, "Настройки сброшены к значениям по умолчанию");
    }

    public int getPathMaxPoints() {
        return prefs.getInt(KEY_PATH_MAX_POINTS, DEFAULT_PATH_MAX_POINTS);
    }

    public void setPathMaxPoints(int maxPoints) {
        if (maxPoints < 10) maxPoints = 10;
        if (maxPoints > 10000) maxPoints = 10000;
        prefs.edit().putInt(KEY_PATH_MAX_POINTS, maxPoints).apply();
    }

    public int getPredictionHorizonSec() {
        return prefs.getInt(KEY_PREDICTION_HORIZON_SEC, DEFAULT_PREDICTION_HORIZON_SEC);
    }

    public void setPredictionHorizonSec(int seconds) {
        if (seconds < 5) seconds = 5;
        if (seconds > 3600) seconds = 3600;
        prefs.edit().putInt(KEY_PREDICTION_HORIZON_SEC, seconds).apply();
    }
    
    /**
     * Получает все настройки в виде строки для отладки
     */
    public String getSettingsSummary() {
        return String.format(
            "UDP: порт=%d, включен=%s\n" +
            "Android NMEA: %s\n" +
            "UDP NMEA: %s\n" +
            "Старт центр по последней: %s, стартовый зум=%.1f\n" +
            "BLE: %s, MAC=%s, Bridge=%s %s:%d\n" +
            "Режим данных: %s\n" +
            "Уведомления: вибрация=%s, звук=%s",
            getUDPPort(),
            isUDPEnabled() ? "да" : "нет",
            isAndroidNMEAEnabled() ? "включен" : "выключен",
            isUDPNMEAEnabled() ? "включен" : "выключен",
            isStartCenterOnLastEnabled() ? "да" : "нет",
            getStartZoomLevel(),
            isBLEEnabled() ? "включен" : "выключен",
            getBLEDeviceMac(),
            isBleUdpBridgeEnabled() ? "вкл" : "выкл",
            getBleUdpBridgeHost(),
            getBleUdpBridgePort(),
            getDataMode(),
            isVibrationEnabled() ? "включена" : "выключена",
            isSoundEnabled() ? "включен" : "выключен"
        );
    }

    // ===== Map startup behavior =====
    public boolean isStartCenterOnLastEnabled() {
        return prefs.getBoolean(KEY_START_CENTER_ON_LAST, DEFAULT_START_CENTER_ON_LAST);
    }

    public void setStartCenterOnLastEnabled(boolean enabled) {
        prefs.edit().putBoolean(KEY_START_CENTER_ON_LAST, enabled).apply();
        Log.i(TAG, "Старт: центр по последней позиции: " + (enabled ? "включен" : "выключен"));
    }

    public float getStartZoomLevel() {
        return prefs.getFloat(KEY_START_ZOOM_LEVEL, DEFAULT_START_ZOOM_LEVEL);
    }

    public void setStartZoomLevel(float zoom) {
        if (zoom < 2.0f) zoom = 2.0f;
        if (zoom > 20.0f) zoom = 20.0f;
        prefs.edit().putFloat(KEY_START_ZOOM_LEVEL, zoom).apply();
        Log.i(TAG, "Стартовый зум установлен: " + zoom);
    }

    public String getMapRotationMode() {
        String m = prefs.getString(KEY_MAP_ROTATION_MODE, DEFAULT_MAP_ROTATION_MODE);
        if (!MAP_ROTATION_MANUAL.equals(m) && !MAP_ROTATION_COMPASS.equals(m) && !MAP_ROTATION_COURSE.equals(m)) {
            return DEFAULT_MAP_ROTATION_MODE;
        }
        return m;
    }

    public void setMapRotationMode(String mode) {
        if (!MAP_ROTATION_MANUAL.equals(mode) && !MAP_ROTATION_COMPASS.equals(mode) && !MAP_ROTATION_COURSE.equals(mode)) {
            mode = DEFAULT_MAP_ROTATION_MODE;
        }
        prefs.edit().putString(KEY_MAP_ROTATION_MODE, mode).apply();
        Log.i(TAG, "Режим вращения карты: " + mode);
    }

    /**
     * Цикл: компас → курс → вручную → компас …
     */
    public String cycleMapRotationMode() {
        String current = getMapRotationMode();
        String next;
        if (MAP_ROTATION_COMPASS.equals(current)) {
            next = MAP_ROTATION_COURSE;
        } else if (MAP_ROTATION_COURSE.equals(current)) {
            next = MAP_ROTATION_MANUAL;
        } else {
            next = MAP_ROTATION_COMPASS;
        }
        setMapRotationMode(next);
        return next;
    }
    
    /**
     * Проверяет, нужно ли перезапустить UDP слушатель
     */
    public boolean shouldRestartUDP(int currentPort, boolean currentEnabled) {
        return getUDPPort() != currentPort || isUDPEnabled() != currentEnabled;
    }
    
    /**
     * Проверяет, нужно ли перезапустить NMEA парсер
     */
    public boolean shouldRestartNMEA(boolean currentAndroidNMEA, boolean currentUDPNMEA, String currentDataMode) {
        return isAndroidNMEAEnabled() != currentAndroidNMEA || 
               isUDPNMEAEnabled() != currentUDPNMEA || 
               !getDataMode().equals(currentDataMode);
    }
    
    /**
     * Получает время предупреждения об устаревших данных (в минутах)
     */
    public int getDataStaleWarningMinutes() {
        return prefs.getInt(KEY_DATA_STALE_WARNING_MINUTES, DEFAULT_DATA_STALE_WARNING_MINUTES);
    }
    
    /**
     * Устанавливает время предупреждения об устаревших данных (в минутах)
     */
    public void setDataStaleWarningMinutes(int minutes) {
        if (minutes < 1 || minutes > 60) {
            Log.w(TAG, "Некорректное время предупреждения: " + minutes + ", используем значение по умолчанию");
            minutes = DEFAULT_DATA_STALE_WARNING_MINUTES;
        }
        prefs.edit().putInt(KEY_DATA_STALE_WARNING_MINUTES, minutes).apply();
        Log.i(TAG, "Время предупреждения об устаревших данных установлено: " + minutes + " минут");
    }
    
    /**
     * Получает время удаления устаревших данных (в минутах)
     */
    public int getDataStaleRemoveMinutes() {
        return prefs.getInt(KEY_DATA_STALE_REMOVE_MINUTES, DEFAULT_DATA_STALE_REMOVE_MINUTES);
    }
    
    /**
     * Устанавливает время удаления устаревших данных (в минутах)
     */
    public void setDataStaleRemoveMinutes(int minutes) {
        if (minutes < 1 || minutes > 60) {
            Log.w(TAG, "Некорректное время удаления: " + minutes + ", используем значение по умолчанию");
            minutes = DEFAULT_DATA_STALE_REMOVE_MINUTES;
        }
        prefs.edit().putInt(KEY_DATA_STALE_REMOVE_MINUTES, minutes).apply();
        Log.i(TAG, "Время удаления устаревших данных установлено: " + minutes + " минут");
    }
    
    /**
     * Проверяет, включено ли отслеживание путей
     */
    public boolean isPathTrackingEnabled() {
        return prefs.getBoolean(KEY_PATH_TRACKING_ENABLED, DEFAULT_PATH_TRACKING_ENABLED);
    }
    
    /**
     * Включает/выключает отслеживание путей
     */
    public void setPathTrackingEnabled(boolean enabled) {
        prefs.edit().putBoolean(KEY_PATH_TRACKING_ENABLED, enabled).apply();
        Log.i(TAG, "Отслеживание путей: " + (enabled ? "включено" : "выключено"));
    }
    
    /**
     * Получает цвет пройденного пути
     */
    public int getPathColor() {
        return prefs.getInt(KEY_PATH_COLOR, DEFAULT_PATH_COLOR);
    }
    
    /**
     * Устанавливает цвет пройденного пути
     */
    public void setPathColor(int color) {
        prefs.edit().putInt(KEY_PATH_COLOR, color).apply();
        Log.i(TAG, "Цвет пройденного пути установлен: " + String.format("#%08X", color));
    }
    
    /**
     * Получает цвет прогнозируемого пути
     */
    public int getPredictionColor() {
        return prefs.getInt(KEY_PREDICTION_COLOR, DEFAULT_PREDICTION_COLOR);
    }
    
    /**
     * Устанавливает цвет прогнозируемого пути
     */
    public void setPredictionColor(int color) {
        prefs.edit().putInt(KEY_PREDICTION_COLOR, color).apply();
        Log.i(TAG, "Цвет прогнозируемого пути установлен: " + String.format("#%08X", color));
    }
    
    /**
     * Получает ширину линии пройденного пути
     */
    public float getPathWidth() {
        return prefs.getFloat(KEY_PATH_WIDTH, DEFAULT_PATH_WIDTH);
    }
    
    /**
     * Устанавливает ширину линии пройденного пути
     */
    public void setPathWidth(float width) {
        if (width < 1.0f || width > 10.0f) {
            Log.w(TAG, "Некорректная ширина пути: " + width + ", используем значение по умолчанию");
            width = DEFAULT_PATH_WIDTH;
        }
        prefs.edit().putFloat(KEY_PATH_WIDTH, width).apply();
        Log.i(TAG, "Ширина пройденного пути установлена: " + width);
    }
    
    /**
     * Получает ширину линии прогнозируемого пути
     */
    public float getPredictionWidth() {
        return prefs.getFloat(KEY_PREDICTION_WIDTH, DEFAULT_PREDICTION_WIDTH);
    }
    
    /**
     * Устанавливает ширину линии прогнозируемого пути
     */
    public void setPredictionWidth(float width) {
        if (width < 1.0f || width > 10.0f) {
            Log.w(TAG, "Некорректная ширина прогноза: " + width + ", используем значение по умолчанию");
            width = DEFAULT_PREDICTION_WIDTH;
        }
        prefs.edit().putFloat(KEY_PREDICTION_WIDTH, width).apply();
        Log.i(TAG, "Ширина прогнозируемого пути установлена: " + width);
    }
    
    /**
     * Проверяет, включена ли вибрация при обнаружении новых AIS целей
     */
    public boolean isVibrationEnabled() {
        return prefs.getBoolean(KEY_VIBRATION_ENABLED, DEFAULT_VIBRATION_ENABLED);
    }
    
    /**
     * Включает/выключает вибрацию при обнаружении новых AIS целей
     */
    public void setVibrationEnabled(boolean enabled) {
        prefs.edit().putBoolean(KEY_VIBRATION_ENABLED, enabled).apply();
        Log.i(TAG, "Вибрация при обнаружении новых AIS целей: " + (enabled ? "включена" : "выключена"));
    }
    
    /**
     * Проверяет, включен ли звук при обнаружении новых AIS целей
     */
    public boolean isSoundEnabled() {
        return prefs.getBoolean(KEY_SOUND_ENABLED, DEFAULT_SOUND_ENABLED);
    }
    
    /**
     * Включает/выключает звук при обнаружении новых AIS целей
     */
    public void setSoundEnabled(boolean enabled) {
        prefs.edit().putBoolean(KEY_SOUND_ENABLED, enabled).apply();
        Log.i(TAG, "Звук при обнаружении новых AIS целей: " + (enabled ? "включен" : "выключен"));
    }
    
    /**
     * Проверяет, включен ли режим "не засыпать" для экрана
     */
    public boolean isKeepScreenOnEnabled() {
        return prefs.getBoolean(KEY_KEEP_SCREEN_ON_ENABLED, DEFAULT_KEEP_SCREEN_ON_ENABLED);
    }
    
    /**
     * Включает/выключает режим "не засыпать" для экрана
     */
    public void setKeepScreenOnEnabled(boolean enabled) {
        prefs.edit().putBoolean(KEY_KEEP_SCREEN_ON_ENABLED, enabled).apply();
        Log.i(TAG, "Режим 'не засыпать' для экрана: " + (enabled ? "включен" : "выключен"));
    }
    
    /**
     * Проверяет, включен ли курсор на карте
     */
    public boolean isCursorEnabled() {
        return prefs.getBoolean(KEY_CURSOR_ENABLED, DEFAULT_CURSOR_ENABLED);
    }
    
    /**
     * Включает/выключает курсор на карте
     */
    public void setCursorEnabled(boolean enabled) {
        prefs.edit().putBoolean(KEY_CURSOR_ENABLED, enabled).apply();
        Log.i(TAG, "Курсор на карте: " + (enabled ? "включен" : "выключен"));
    }
    
    /**
     * Проверяет, включены ли уведомления
     */
    public boolean areNotificationsEnabled() {
        return prefs.getBoolean(KEY_NOTIFICATIONS_ENABLED, DEFAULT_NOTIFICATIONS_ENABLED);
    }
    
    /**
     * Включает/выключает уведомления
     */
    public void setNotificationsEnabled(boolean enabled) {
        prefs.edit().putBoolean(KEY_NOTIFICATIONS_ENABLED, enabled).apply();
        Log.i(TAG, "Уведомления: " + (enabled ? "включены" : "выключены"));
    }

    /**
     * Проверяет, включен ли дебаг-режим
     */
    public boolean isDebugEnabled() {
        return prefs.getBoolean(KEY_DEBUG_ENABLED, DEFAULT_DEBUG_ENABLED);
    }

    /**
     * Включает/выключает дебаг-режим
     */
    public void setDebugEnabled(boolean enabled) {
        prefs.edit().putBoolean(KEY_DEBUG_ENABLED, enabled).apply();
        Log.i(TAG, "Дебаг-режим: " + (enabled ? "включен" : "выключен"));
    }
    
    /**
     * Проверяет, включены ли морские знаки OpenSeaMap
     */
    public boolean isSeamarksEnabled() {
        return prefs.getBoolean(KEY_SEAMARKS_ENABLED, DEFAULT_SEAMARKS_ENABLED);
    }

    /**
     * Включает/выключает морские знаки OpenSeaMap
     */
    public void setSeamarksEnabled(boolean enabled) {
        prefs.edit().putBoolean(KEY_SEAMARKS_ENABLED, enabled).apply();
        Log.i(TAG, "Морские знаки OpenSeaMap: " + (enabled ? "включены" : "выключены"));
    }
    
}
