package com.grigowashere.aismap.models;

import java.time.LocalDateTime;

/**
 * Модель AIS навигационного знака (буйка, маяка, платформы и т.д.)
 * Специализированный класс для сообщений типа 21 (Aid-to-Navigation Report)
 */
public class AISNavigationAid {
    private String mmsi; // Maritime Mobile Service Identity
    private String aidName; // название навигационного знака
    private int aidType; // тип навигационного знака (0-30)
    private String aidTypeDescription; // описание типа
    private double latitude;
    private double longitude;
    private boolean positionAccuracy; // точность позиции
    
    // Размеры навигационного знака
    private double length; // длина в метрах
    private double width; // ширина в метрах
    private double draft; // осадка в метрах
    
    // Dimension Reference поля (для коротких сообщений)
    private int dimRefA; // от носа до антенны
    private int dimRefB; // от антенны до кормы
    private int dimRefC; // от левого борта до антенны
    private int dimRefD; // от антенны до правого борта
    
    // Дополнительные поля для полных сообщений
    private int epfdType; // тип электронного устройства позиционирования
    private int utcSecond; // секунда UTC timestamp
    private boolean offPositionIndicator; // индикатор смещения с позиции
    private int regionalReserved; // зарезервировано для регионального использования
    private boolean raimFlag; // флаг RAIM (Receiver Autonomous Integrity Monitoring)
    
    private LocalDateTime lastUpdate;
    private boolean isActive; // активно ли устройство
    private boolean selected; // выделено ли на карте

    public AISNavigationAid() {
        this.lastUpdate = LocalDateTime.now();
        this.isActive = true;
    }

    public AISNavigationAid(String mmsi) {
        this();
        this.mmsi = mmsi;
    }

    // Геттеры и сеттеры
    public String getMmsi() { return mmsi; }
    public void setMmsi(String mmsi) { this.mmsi = mmsi; }

    public String getAidName() { return aidName; }
    public void setAidName(String aidName) { this.aidName = aidName; }

    public int getAidType() { return aidType; }
    public void setAidType(int aidType) { 
        this.aidType = aidType;
        this.aidTypeDescription = getAidTypeDescription(aidType);
    }

    public String getAidTypeDescription() { return aidTypeDescription; }
    public void setAidTypeDescription(String aidTypeDescription) { this.aidTypeDescription = aidTypeDescription; }

    public double getLatitude() { return latitude; }
    public void setLatitude(double latitude) { this.latitude = latitude; }

    public double getLongitude() { return longitude; }
    public void setLongitude(double longitude) { this.longitude = longitude; }

    public boolean isPositionAccuracy() { return positionAccuracy; }
    public void setPositionAccuracy(boolean positionAccuracy) { this.positionAccuracy = positionAccuracy; }

    public double getLength() { return length; }
    public void setLength(double length) { this.length = length; }

    public double getWidth() { return width; }
    public void setWidth(double width) { this.width = width; }

    public double getDraft() { return draft; }
    public void setDraft(double draft) { this.draft = draft; }

    public int getDimRefA() { return dimRefA; }
    public void setDimRefA(int dimRefA) { this.dimRefA = dimRefA; }

    public int getDimRefB() { return dimRefB; }
    public void setDimRefB(int dimRefB) { this.dimRefB = dimRefB; }

    public int getDimRefC() { return dimRefC; }
    public void setDimRefC(int dimRefC) { this.dimRefC = dimRefC; }

    public int getDimRefD() { return dimRefD; }
    public void setDimRefD(int dimRefD) { this.dimRefD = dimRefD; }

    public int getEpfdType() { return epfdType; }
    public void setEpfdType(int epfdType) { this.epfdType = epfdType; }

    public int getUtcSecond() { return utcSecond; }
    public void setUtcSecond(int utcSecond) { this.utcSecond = utcSecond; }

    public boolean isOffPositionIndicator() { return offPositionIndicator; }
    public void setOffPositionIndicator(boolean offPositionIndicator) { this.offPositionIndicator = offPositionIndicator; }

    public int getRegionalReserved() { return regionalReserved; }
    public void setRegionalReserved(int regionalReserved) { this.regionalReserved = regionalReserved; }

    public boolean isRaimFlag() { return raimFlag; }
    public void setRaimFlag(boolean raimFlag) { this.raimFlag = raimFlag; }

    public LocalDateTime getLastUpdate() { return lastUpdate; }
    public void setLastUpdate(LocalDateTime lastUpdate) { this.lastUpdate = lastUpdate; }

    public boolean isActive() { return isActive; }
    public void setActive(boolean active) { isActive = active; }

    public boolean isSelected() { return selected; }
    public void setSelected(boolean selected) { this.selected = selected; }

    /**
     * Обновляет позицию навигационного знака
     */
    public void updatePosition(double latitude, double longitude) {
        this.latitude = latitude;
        this.longitude = longitude;
        this.lastUpdate = LocalDateTime.now();
    }

    /**
     * Проверяет, не устарели ли данные на указанное количество минут
     */
    public boolean isDataStale(int warningMinutes) {
        return LocalDateTime.now().minusMinutes(warningMinutes).isAfter(lastUpdate);
    }
    
    /**
     * Проверяет, нужно ли удалить данные (старше указанного количества минут)
     */
    public boolean shouldBeRemoved(int removeMinutes) {
        return LocalDateTime.now().minusMinutes(removeMinutes).isAfter(lastUpdate);
    }
    
    /**
     * Получает количество минут с последнего обновления
     */
    public long getMinutesSinceLastUpdate() {
        return java.time.Duration.between(lastUpdate, LocalDateTime.now()).toMinutes();
    }

    /**
     * Получает описание типа электронного устройства позиционирования
     */
    public String getEpfdTypeDescription() {
        switch (epfdType) {
            case 0: return "Undefined";
            case 1: return "GPS";
            case 2: return "GLONASS";
            case 3: return "Combined GPS/GLONASS";
            case 4: return "Loran-C";
            case 5: return "Chayka";
            case 6: return "Integrated navigation system";
            case 7: return "Surveyed";
            case 8:
            case 9:
            case 10:
            case 11:
            case 12:
            case 13:
            case 14:
            case 15: return "Not used";
            default: return "Unknown";
        }
    }

    /**
     * Получает описание типа навигационного знака по коду
     */
    private String getAidTypeDescription(int aidType) {
        switch (aidType) {
            case 0: return "Reference point";
            case 1: return "RACON (radar transponder marking a navigation hazard)";
            case 2: return "Fixed structure off shore, such as oil platforms, wind farms, rigs";
            case 3: return "Spare, Reserved for future use";
            case 4: return "Light, without sectors";
            case 5: return "Light, with sectors";
            case 6: return "Leading Light Front";
            case 7: return "Leading Light Rear";
            case 8: return "Beacon, Cardinal N";
            case 9: return "Beacon, Cardinal E";
            case 10: return "Beacon, Cardinal S";
            case 11: return "Beacon, Cardinal W";
            case 12: return "Beacon, Port hand";
            case 13: return "Beacon, Starboard hand";
            case 14: return "Beacon, Preferred Channel port hand";
            case 15: return "Beacon, Preferred Channel starboard hand";
            case 16: return "Beacon, Isolated danger";
            case 17: return "Beacon, Safe water";
            case 18: return "Beacon, Special mark";
            case 19: return "Cardinal Mark N";
            case 20: return "Cardinal Mark E";
            case 21: return "Cardinal Mark S";
            case 22: return "Cardinal Mark W";
            case 23: return "Port hand Mark";
            case 24: return "Starboard hand Mark";
            case 25: return "Preferred Channel port hand";
            case 26: return "Preferred Channel starboard hand";
            case 27: return "Isolated danger";
            case 28: return "Safe water";
            case 29: return "Special mark";
            case 30: return "Light Vessel / LANBY / Rigs";
            default: return "Unknown Aid-to-Navigation";
        }
    }

    /**
     * Вычисляет общие размеры из Dimension Reference полей
     */
    public void calculateDimensionsFromRefs() {
        this.length = dimRefA + dimRefB;
        this.width = dimRefC + dimRefD;
    }

    /**
     * Проверяет, является ли это буйком (Cardinal Mark)
     */
    public boolean isCardinalMark() {
        return aidType >= 19 && aidType <= 22;
    }

    /**
     * Проверяет, является ли это маяком
     */
    public boolean isLight() {
        return aidType >= 4 && aidType <= 7;
    }

    /**
     * Проверяет, является ли это платформой или стационарной конструкцией
     */
    public boolean isFixedStructure() {
        return aidType == 2 || aidType == 30;
    }

    @Override
    public String toString() {
        return "AISNavigationAid{" +
                "mmsi='" + mmsi + '\'' +
                ", name='" + aidName + '\'' +
                ", type=" + aidType + " (" + aidTypeDescription + ")" +
                ", lat=" + latitude +
                ", lon=" + longitude +
                ", L=" + length +
                ", W=" + width +
                ", D=" + draft +
                '}';
    }
}
