extends Label

enum DEVICE_STATE {
    NONE,    # Нет связи
    GOOD,    # Исправно
    ERR      # Отказ
}

enum DEVICE_STATUS {
    ONLINE,      # Связь есть
    STATUS,      # Статус исправности
    CONTROL      # Контроль завершен
}

const STATUS_CONFIG := {
    DEVICE_STATE.NONE: {'text': 'Нет связи', 'color': Color.WHITE, 'font_color': Color.BLACK},
    DEVICE_STATE.GOOD: {'text': 'Исправно', 'color': Color.GREEN, 'font_color': Color.BLACK},
    DEVICE_STATE.ERR: {'text': 'Отказ', 'color': Color.RED, 'font_color': Color.WHITE}
}

class DeviceObserver:
    var device_name: String
    var status: Array = [false, false, false]  # [online, operational, control_complete]
    var last_results: Dictionary = {}

    func update_online_state(online: bool) -> bool:
        if status[DEVICE_STATUS.ONLINE] != online:
            status[DEVICE_STATUS.ONLINE] = online
            return true
        return false

    func update_control_results(results: Dictionary) -> bool:
        var changed := false

        if results.get('is_over_control', false):
            # Контроль завершен - проверяем все результаты
            var all_ok := true
            for key in results:
                if key != 'is_over_control' and not results[key]:
                    all_ok = false
                    break

            if status[DEVICE_STATUS.STATUS] != all_ok or status[DEVICE_STATUS.CONTROL] != true:
                status[DEVICE_STATUS.STATUS] = all_ok
                status[DEVICE_STATUS.CONTROL] = true
                changed = true
        else:
            # Контроль в процессе - проверяем базовые параметры
            var basic_ok: bool = results.get('block_kasseta', false) and \
                           results.get('block_ip', false) and \
                           results.get('temperature', true)

            if status[DEVICE_STATUS.STATUS] != basic_ok or status[DEVICE_STATUS.CONTROL] != false:
                status[DEVICE_STATUS.STATUS] = basic_ok
                status[DEVICE_STATUS.CONTROL] = false
                changed = true
        return changed

var device_observers: Dictionary = {}
var overall_prd_state: DEVICE_STATE = DEVICE_STATE.NONE
var status_uf: int = DEVICE_STATE.NONE  # Статус УФ (УАРЭП-ЭМС)

func _ready() -> void:
    tooltip_text = 'Нет связи с приборами комплекса'
    add_theme_color_override("font_color", Color.BLACK)

    # Инициализация наблюдателей
    _initialize_observers()

    # Подписка на сигналы ПРД модулей
    for prd_module in prd.prd_dict.values():
        # Подключаемся к контролю ПРД
        if prd_module.unit_control:
            prd_module.unit_control.connect('control_results_updated', Callable(self, '_on_prd_control_results').bind(prd_module))
        # Подключаемся к онлайн-статусу ЯУ-07
        if prd_module.unit_yau07:
            prd_module.unit_yau07.connect('line_changed', Callable(self, '_on_prd_online_changed').bind(prd_module))

    # Подписка на УФ
    signaller.connect('update_uf_serviceability', _on_uf_status_receive)

    # Инициализация начального состояния
    _recalculate_overall_state()


func _initialize_observers() -> void:
    var device_names := [
        'уарэп-яу07-1н', 'уарэп-яу07-1в', 'уарэп-яу07-1к',
        'уарэп-яу07-2н', 'уарэп-яу07-2в', 'уарэп-яу07-2к',
        'уарэп-яу07-3н', 'уарэп-яу07-3в', 'уарэп-яу07-3к',
        'уарэп-яу07-4н', 'уарэп-яу07-4в', 'уарэп-яу07-4к'
    ]

    for device_name in device_names:
        device_observers[device_name] = DeviceObserver.new()
        device_observers[device_name].device_name = device_name


func _on_prd_online_changed(line_status: Object, prd_module: Object) -> void:
    var online: bool = line_status.online
    var observer: DeviceObserver = device_observers.get(prd_module.prd_name)
    if observer and observer.update_online_state(online):
        _recalculate_overall_state()


func _on_prd_control_results(results: Dictionary, prd_module: Object) -> void:
    var observer: DeviceObserver = device_observers.get(prd_module.prd_name)
    if observer and observer.update_control_results(results):
        _recalculate_overall_state()


func _on_uf_status_receive(unit_uf_status: int) -> void:
    if status_uf != unit_uf_status:
        status_uf = unit_uf_status
        _recalculate_overall_state()


func _recalculate_overall_state() -> void:
    var new_state := DEVICE_STATE.NONE

    # Проверяем статус ПРД
    var prd_state := DEVICE_STATE.NONE
    var has_online_prd := false
    var all_prd_operational := true

    for observer in device_observers.values():
        if observer.status[DEVICE_STATUS.ONLINE]:
            has_online_prd = true

            if observer.status[DEVICE_STATUS.CONTROL]:
                if not observer.status[DEVICE_STATUS.STATUS]:
                    all_prd_operational = false
                    break
            else:
                if not observer.status[DEVICE_STATUS.STATUS]:
                    all_prd_operational = false

    if has_online_prd:
        if all_prd_operational:
            prd_state = DEVICE_STATE.GOOD
        else:
            prd_state = DEVICE_STATE.ERR
    else:
        prd_state = DEVICE_STATE.NONE

    # Комбинируем статусы по правилу:
    # 1. Если хоть один ERROR → ERROR
    # 2. Если нет ERROR и хоть один GOOD → GOOD
    # 3. Иначе → NONE

    if prd_state == DEVICE_STATE.ERR or status_uf == DEVICE_STATE.ERR:
        new_state = DEVICE_STATE.ERR
    elif prd_state == DEVICE_STATE.GOOD or status_uf == DEVICE_STATE.GOOD:
        new_state = DEVICE_STATE.GOOD
    else:
        new_state = DEVICE_STATE.NONE

    if overall_prd_state != new_state:
        overall_prd_state = new_state
        _update_display()


func _update_display() -> void:
    var config: Dictionary = STATUS_CONFIG[overall_prd_state]
    text = config.text
    modulate = config.color
    add_theme_color_override('font_color', config.font_color)
    tooltip_text = _get_tooltip_text()


func _get_tooltip_text() -> String:
    var tooltip := ''

    # Получаем статистику по ПРД
    var prd_summary = _get_prd_summary()
    var uf_status_str = _get_uf_status_text()

    match overall_prd_state:
        DEVICE_STATE.NONE:
            tooltip = 'Нет исправных систем в комплексе'
        DEVICE_STATE.GOOD:
            tooltip = 'Комплекс исправен'
        DEVICE_STATE.ERR:
            tooltip = 'Обнаружены неисправности в комплексе'

    tooltip += '\n\nСтатус ПРД систем: ' + prd_summary
    tooltip += '\nСтатус УФ: ' + uf_status_str

    # Детализация по источникам статуса
    tooltip += '\n\nСостояние систем:'

    # ПРД системы
    var prd_ok_count = 0
    var prd_total = 0
    for observer in device_observers.values():
        if observer.status[DEVICE_STATUS.ONLINE]:
            prd_total += 1
            if observer.status[DEVICE_STATUS.STATUS]:
                prd_ok_count += 1

    tooltip += '\nПРД: %d/%d исправно' % [prd_ok_count, prd_total]

    # УФ система
    tooltip += '\nУФ: ' + _get_uf_status_text()

    return tooltip


func _get_prd_summary() -> String:
    var online_count := 0
    var operational_count := 0

    for observer in device_observers.values():
        if observer.status[DEVICE_STATUS.ONLINE]:
            online_count += 1
            if observer.status[DEVICE_STATUS.STATUS]:
                operational_count += 1

    if online_count == 0:
        return 'Нет связи'
    else:
        return '%d/%d исправно' % [operational_count, online_count]


func _get_uf_status_text() -> String:
    match status_uf:
        DEVICE_STATE.NONE:
            return 'Нет данных'
        DEVICE_STATE.GOOD:
            return 'Исправен'
        DEVICE_STATE.ERR:
            return 'Неисправен'
        _:
            return 'Неизвестно'


func _has_prd_errors() -> bool:
    for observer in device_observers.values():
        if observer.status[DEVICE_STATUS.ONLINE] and not observer.status[DEVICE_STATUS.STATUS]:
            return true
    return false


func _has_operational_prd() -> bool:
    for observer in device_observers.values():
        if observer.status[DEVICE_STATUS.ONLINE] and observer.status[DEVICE_STATUS.STATUS]:
            return true
    return false


# Публичные методы для получения информации
func get_device_status(device_name: String) -> Dictionary:
    var observer: DeviceObserver = device_observers.get(device_name)
    if observer:
        return {
            'online': observer.status[DEVICE_STATUS.ONLINE],
            'operational': observer.status[DEVICE_STATUS.STATUS],
            'control_complete': observer.status[DEVICE_STATUS.CONTROL],
            'last_results': observer.last_results,
            'status_uf': status_uf
        }
    return {}


func get_overall_status() -> Dictionary:
    var online_count := 0
    var operational_count := 0
    var control_complete_count := 0

    for observer in device_observers.values():
        if observer.status[DEVICE_STATUS.ONLINE]:
            online_count += 1
            if observer.status[DEVICE_STATUS.STATUS]:
                operational_count += 1
            if observer.status[DEVICE_STATUS.CONTROL]:
                control_complete_count += 1

    return {
        'overall_state': overall_prd_state,
        'online_devices': online_count,
        'operational_devices': operational_count,
        'total_devices': device_observers.size(),
        'control_complete_devices': control_complete_count,
        'uf_status': status_uf
    }
