extends Node2D

signal read_ems_g_start()
signal read_ems_g_finish()
signal write_ems_g_start()

var timer_modul_um: Timer = Timer.new()

var node_select1: Node
var node_select2: Node
var node_select3: Node
var node_select_yau_07b: Node
var node_select_yau_07b_2: Node
var node_select_fs_1: Node
var node_select_fs_2: Node
var node_select_fs_3: Node
var isa_from_yau07b: Dictionary = {}
var freq_fs_1: int
var freq_fs_2: int
var freq_fs_3: int
var att_fs_1: float
var att_fs_2: float
var att_fs_3: float
var status_pribor = null
var save_path = "res://saves/"
var current_meta: Array = [Constants.META.MODUL_UM_1, Constants.META.MODUL_UM_2, Constants.META.MODUL_UM_3, Constants.META.MODUL_UM_28]
var modul_um: Array = [0, 0, 0, 0]
var receive_yau_counter: Array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
const need_port: Array = [0x122, 0x124, 0x126, 0x128, 0x12A]
const TIMER_BLOCK_EMS: float = 2.0


func _ready() -> void:
    $Background/notice/lbl_commit.text = commit.VCS_HEAD
    $Background/notice/bind_addr.text = '/Базовый адрес: %s' % Constants.UNICAST_ADDRESS

    # Таблица 1 УКП-1 (Температура, Мощность)
    node_select1 = $TabContainer/PRD/body_grid/litera_2_4_6/table_ukp_1
    draw_tabl(node_select1, Constants.ROWS_REGS_DATA, Constants.ROWS_REGS_DATA.size())
    node_select1.set_columns_min_size([120, 120])

    # Таблица 2 УКП-2 (Температура, Мощность)
    node_select2 = $TabContainer/PRD/body_grid/litera_3_5_7/table_ukp_2
    draw_tabl(node_select2, Constants.ROWS_REGS_DATA, Constants.ROWS_REGS_DATA.size())
    node_select2.set_columns_min_size([120, 120])

    # Таблица 3 УКП-1 (Температура, Мощность)
    node_select3 = $TabContainer/PRD/body_grid/litera_1/table_ukp_1
    draw_tabl(node_select3, [[preload("res://table/header.tscn"), preload("res://table/header.tscn")], [preload("res://table/node.tscn"), preload("res://table/node.tscn")]], [[preload("res://table/header.tscn"), preload("res://table/header.tscn")], [preload("res://table/node.tscn"), preload("res://table/node.tscn")]].size())
    node_select3.set_columns_min_size([120, 120])

    # Таблица ЯУ-07б-1
    node_select_yau_07b = $TabContainer/PRD/body_grid/litera_2_4_6/yau07b_control
    draw_tabl(node_select_yau_07b, Constants.ROWS_YAU_07B_2, Constants.ROWS_YAU_07B_2.size())
    node_select_yau_07b.set_columns_min_size([160, 120])
    node_select_yau_07b.get_node2(1, 1).get_child(1).tooltip_text = 'Переключение запрета си в уф'
    node_select_yau_07b.get_node2(1, 5).get_child(1).tooltip_text = 'Переключение сигнала ФГОЗ'

    # Таблица ЯУ-07б-2
    node_select_yau_07b_2 = $TabContainer/PRD/body_grid/litera_3_5_7/yau07b_control
    draw_tabl(node_select_yau_07b_2, Constants.ROWS_YAU_07B_2, Constants.ROWS_YAU_07B_2.size())
    node_select_yau_07b_2.set_columns_min_size([160, 120])
    node_select_yau_07b_2.get_node2(1, 1).get_child(1).tooltip_text = 'Переключение запрета си в уф'
    node_select_yau_07b_2.get_node2(1, 5).get_child(1).tooltip_text = 'Переключение сигнала ФГОЗ'

    # Таблица ЯУ-07б-3
    var node_select_yau_07b_3: Node = $TabContainer/PRD/body_grid/litera_1/yau07b_control
    draw_tabl(node_select_yau_07b_3, Constants.ROWS_YAU_07B_2, Constants.ROWS_YAU_07B_2.size())
    node_select_yau_07b_3.set_columns_min_size([160, 120])

    #Таблица ФС-1
    node_select_fs_1 = $TabContainer/PRD/body_grid/litera_2_4_6/fs_control
    draw_tabl(node_select_fs_1, Constants.ROWS_FS, Constants.ROWS_FS.size())
    node_select_fs_1.set_columns_min_size([150, 120, 150])
    node_select_fs_1.get_node2(1, 4).add_item('Const')
    node_select_fs_1.get_node2(1, 4).add_item('MSK')

    #Таблица ФС-2
    node_select_fs_2 = $TabContainer/PRD/body_grid/litera_3_5_7/fs_control
    draw_tabl(node_select_fs_2, Constants.ROWS_FS, Constants.ROWS_FS.size())
    node_select_fs_2.set_columns_min_size([150, 120, 150])
    node_select_fs_2.get_node2(1, 4).add_item('Const')
    node_select_fs_2.get_node2(1, 4).add_item('MSK')

    #Таблица ФС-3
    node_select_fs_3 = $TabContainer/PRD/body_grid/litera_1/fs_control
    draw_tabl(node_select_fs_3, Constants.ROWS_FS, Constants.ROWS_FS.size())
    node_select_fs_3.set_columns_min_size([150, 120, 150])

    # Таблица ЯУ-07б-3
    var item_place_yau_07_3: int = 38
    node_select_yau_07b_3.set_node_text(0, 0, Constants.SIGNS[Constants.MODE.PRD_K][item_place_yau_07_3+0]) # 'ПРД-Н'
    node_select_yau_07b_3.set_node_text(1, 0, Constants.SIGNS[Constants.MODE.PRD_K][item_place_yau_07_3+1]) # 'Литера 1'
    node_select_yau_07b_3.set_node_text(0, 1, Constants.SIGNS[Constants.MODE.PRD_K][item_place_yau_07_3+2]) # 'Запрет СИ 1'
    node_select_yau_07b_3.set_node_text(0, 2, Constants.SIGNS[Constants.MODE.PRD_K][item_place_yau_07_3+3]) # 'Модуляция УМ'
    node_select_yau_07b_3.set_node_text(0, 3, Constants.SIGNS[Constants.MODE.PRD_K][item_place_yau_07_3+4]) # 'Положение луча'
    node_select_yau_07b_3.set_node_text(0, 4, Constants.SIGNS[Constants.MODE.PRD_K][item_place_yau_07_3+5]) # 'Аттенюатор УМ'
    node_select_yau_07b_3.get_node2(1, 5).get_child(1).visible = false
    node_select_yau_07b_3.set_node_text(0, 5, Constants.SIGNS[Constants.MODE.PRD_K][item_place_yau_07_3+6]) # 'ФГОЗ'
    node_select_yau_07b_3.set_node_text(0, 6, Constants.SIGNS[Constants.MODE.PRD_K][item_place_yau_07_3+7]) # 'СИ 1 в УФ'
    node_select_yau_07b_3.set_node_text(0, 7, Constants.SIGNS[Constants.MODE.PRD_K][item_place_yau_07_3+8]) # 'СЗИ 1 от УФ'

    #Таблица ФС-3
    var item_place_fs_3: int = 47
    node_select_fs_3.set_node_text(0, 0, Constants.SIGNS[Constants.MODE.PRD_K][item_place_fs_3+0]) # 'Модуль ФС 1'
    node_select_fs_3.set_node_text(1, 0, Constants.SIGNS[Constants.MODE.PRD_K][item_place_fs_3+1]) # 'Литера ФС 1'
    node_select_fs_3.set_node_text(0, 1, Constants.SIGNS[Constants.MODE.PRD_K][item_place_fs_3+2]) # 'Состояние'
    node_select_fs_3.set_node_text(0, 2, Constants.SIGNS[Constants.MODE.PRD_K][item_place_fs_3+3]) # 'Частота'
    node_select_fs_3.get_node2(1, 2).placeholder_text = 'в МГц'
    node_select_fs_3.get_node2(1, 2).editable = true
    node_select_fs_3.set_node_text(0, 3, Constants.SIGNS[Constants.MODE.PRD_K][item_place_fs_3+4]) # 'Аттенюатор ФС'
    node_select_fs_3.get_node2(1, 3).placeholder_text = 'в dB'
    node_select_fs_3.get_node2(1, 3).editable = true
    node_select_fs_3.set_node_text(0, 4, Constants.SIGNS[Constants.MODE.PRD_K][item_place_fs_3+5]) # 'Модуляция ФС 1'
    node_select_fs_3.get_node2(1, 4).add_item('Const')
    node_select_fs_3.get_node2(1, 4).add_item('MSK')
    node_select_fs_3.set_node_text(0, 5, Constants.SIGNS[Constants.MODE.PRD_K][item_place_fs_3+6]) # 'Генератор ФС'
    node_select_fs_3.set_node_text(0, 6, Constants.SIGNS[Constants.MODE.PRD_K][item_place_fs_3+7]) # 'СИ 1 от ФС'
    node_select_fs_3.set_node_text(0, 7, Constants.SIGNS[Constants.MODE.PRD_K][item_place_fs_3+8]) # 'Фильтр CAN'
    node_select_fs_3.get_node2(1, 7).placeholder_text = 'в МГц'
    node_select_fs_3.get_node2(1, 7).editable = true
    node_select_fs_3.set_node_text(0, 8, Constants.SIGNS[Constants.MODE.PRD_K][item_place_fs_3+9]) # 'Статус CAN')

    # Выбор прибора для подключения
    var node_select_device: Node = $TabContainer/PRD/select_dev
    draw_tabl(node_select_device, Constants.SELECT_DEVICE, Constants.SELECT_DEVICE.size())
    var get_select_device: Node = node_select_device.get_node2(1, 0)
    for i_addr in Constants.ADDRESSES.size():   # Заполнение адресов
        get_select_device.add_item(Constants.ADDRESSES[i_addr][0])
        get_select_device.set_item_metadata(i_addr, Constants.ADDRESSES[i_addr].slice(1,7))
    node_select_device.get_node2(0,0).text = 'ПРИБОР'
    node_select_device.set_columns_min_size([100, 100])

    # Получение выбранного прибора при загрузке
    status_pribor = Constants.CURRENT_MODE

    add_signs_scene()

    ## Заполненение списка модуляции УМ
    for key in Constants.OUT_x128:
        node_select_yau_07b.get_node2(1, 2).add_item(key)
        node_select_yau_07b_2.get_node2(1, 2).add_item(key)
        node_select_yau_07b_3.get_node2(1, 2).add_item(key)

    node_select_yau_07b.get_node2(1, 2).set_meta('meta_um', Constants.META.MODUL_UM_2)
    node_select_yau_07b_2.get_node2(1, 2).set_meta('meta_um', Constants.META.MODUL_UM_3)
    node_select_yau_07b_3.get_node2(1, 2).set_meta('meta_um', Constants.META.MODUL_UM_1)

    ## Заполненение списка направления луча
    for key in Constants.RAY_DICT:
        node_select_yau_07b.get_node2(1, 3).add_item(key)
        node_select_yau_07b_2.get_node2(1, 3).add_item(key)

    node_select_yau_07b_3.get_node2(1, 3).add_item('  15°')

    ## Заполненение списка аттенюатора
    for key in Constants.ATT_DICT:
        node_select_yau_07b.get_node2(1, 4).add_item(key)

    ## Заполненение списка аттенюатора
    for key in Constants.ATT_DICT_correct:
        node_select_yau_07b_3.get_node2(1, 4).add_item(key)

    ## EMS статус сокета
    $TabContainer/EMS_G.CI_1_UF = $TabContainer/PRD/body_grid/litera_1/yau07b_control.get_node2(1, 6).get_child(1)
    $TabContainer/EMS_G.CI_2_UF = $TabContainer/PRD/body_grid/litera_2_4_6/yau07b_control.get_node2(1, 6).get_child(1)
    $TabContainer/EMS_G.CI_3_UF = $TabContainer/PRD/body_grid/litera_3_5_7/yau07b_control.get_node2(1, 6).get_child(1)
    $TabContainer/EMS_G.CZI_1_FS = $TabContainer/PRD/body_grid/litera_1/yau07b_control.get_node2(1, 7).get_child(1)
    $TabContainer/EMS_G.CZI_2_FS = $TabContainer/PRD/body_grid/litera_2_4_6/yau07b_control.get_node2(1, 7).get_child(1)
    $TabContainer/EMS_G.CZI_3_FS = $TabContainer/PRD/body_grid/litera_3_5_7/yau07b_control.get_node2(1, 7).get_child(1)
    $TabContainer/EMS_G.CZI_4_FS = $TabContainer/PRD/body_grid/litera_2_4_6/yau07b_control.get_node2(1, 7).get_child(1)
    $TabContainer/EMS_G.CZI_5_FS = $TabContainer/PRD/body_grid/litera_3_5_7/yau07b_control.get_node2(1, 7).get_child(1)
    $TabContainer/EMS_G.CZI_6_FS = $TabContainer/PRD/body_grid/litera_2_4_6/yau07b_control.get_node2(1, 7).get_child(1)
    $TabContainer/EMS_G.CZI_7_FS = $TabContainer/PRD/body_grid/litera_3_5_7/yau07b_control.get_node2(1, 7).get_child(1)
    $TabContainer/EMS_G.CI_2_FS = $TabContainer/PRD/body_grid/litera_2_4_6/fs_control.get_node2(1, 6).get_child(1)
    $TabContainer/EMS_G.CI_3_FS = $TabContainer/PRD/body_grid/litera_3_5_7/fs_control.get_node2(1, 6).get_child(1)
    $TabContainer/EMS_G.CI_4_FS = $TabContainer/PRD/body_grid/litera_2_4_6/fs_control.get_node2(1, 6).get_child(1)
    $TabContainer/EMS_G.CI_5_FS = $TabContainer/PRD/body_grid/litera_3_5_7/fs_control.get_node2(1, 6).get_child(1)
    $TabContainer/EMS_G.CI_1_FS = $TabContainer/PRD/body_grid/litera_1/fs_control.get_node2(1, 6).get_child(1)
    $TabContainer/EMS_G.CI_6_FS = $TabContainer/PRD/body_grid/litera_2_4_6/fs_control.get_node2(1, 6).get_child(1)
    $TabContainer/EMS_G.CI_7_FS = $TabContainer/PRD/body_grid/litera_3_5_7/fs_control.get_node2(1, 6).get_child(1)

    get_select_device.connect('item_selected', Callable(self, 'on_mode_select'))

    ## Yau-07b 1
    node_select_yau_07b.get_node2(1, 1).get_child(1, false).connect('toggled', Callable(self, '_on_zapret_2'))
    node_select_yau_07b.get_node2(1, 2).connect('item_selected', Callable(self, '_on_modul_um').bind(node_select_yau_07b.get_node2(1, 2)))
    node_select_yau_07b.get_node2(1, 3).connect('item_selected', Callable(self, '_on_btn_ray_1'))
    node_select_yau_07b.get_node2(1, 4).connect('item_selected', Callable(self, '_on_attenuator_1'))
    node_select_yau_07b.get_node2(1, 5).get_child(1, false).connect('toggled', Callable(self, '_on_fgos_1'))
    ## Yau-07b 2
    node_select_yau_07b_2.get_node2(1, 1).get_child(1, false).connect('toggled', Callable(self, '_on_zapret_3'))
    node_select_yau_07b_2.get_node2(1, 2).connect('item_selected', Callable(self, '_on_modul_um').bind(node_select_yau_07b_2.get_node2(1, 2)))
    node_select_yau_07b_2.get_node2(1, 3).connect('item_selected', Callable(self, '_on_btn_ray_2'))
    node_select_yau_07b_2.get_node2(1, 4).connect('item_selected', Callable(self, '_on_attenuator_2'))
    node_select_yau_07b_2.get_node2(1, 5).get_child(1, false).connect('toggled', Callable(self, '_on_fgos_2'))
    ## Yau-07b 3
    node_select_yau_07b_3.get_node2(1, 1).get_child(1, false).connect('toggled', Callable(self, '_on_zapret_1'))
    node_select_yau_07b_3.get_node2(1, 2).connect('item_selected', Callable(self, '_on_modul_um').bind(node_select_yau_07b_3.get_node2(1, 2)))
    node_select_yau_07b_3.get_node2(1, 4).connect('item_selected', Callable(self, '_on_attenuator_3'))

    ## FS 1
    node_select_fs_1.get_node2(1, 2).connect('text_submitted', Callable(self, '_on_set_ferq').bind(Network.unit_fs_1))
    node_select_fs_1.get_node2(1, 3).connect('text_submitted', Callable(self, '_on_set_att').bind(Network.unit_fs_1))
    node_select_fs_1.get_node2(1, 4).connect('item_selected', Callable(self, '_on_modul_fs').bind(Network.unit_fs_1))
    node_select_fs_1.get_node2(1, 5).get_child(1, false).connect('toggled', Callable(self, '_on_get_status').bind(Network.unit_fs_1))
    node_select_fs_1.get_node2(1, 7).connect('text_submitted', Callable(self, '_on_set_base_can_macro').bind(Network.unit_fs_1))
    node_select_fs_1.get_node2(1, 8).get_child(1, false).connect('toggled', Callable(self, '_on_status_can_macro').bind(Network.unit_fs_1))
    ## FS 2
    node_select_fs_2.get_node2(1, 2).connect('text_submitted', Callable(self, '_on_set_ferq').bind(Network.unit_fs_2))
    node_select_fs_2.get_node2(1, 3).connect('text_submitted', Callable(self, '_on_set_att').bind(Network.unit_fs_2))
    node_select_fs_2.get_node2(1, 4).connect('item_selected', Callable(self, '_on_modul_fs').bind(Network.unit_fs_2))
    node_select_fs_2.get_node2(1, 5).get_child(1, false).connect('toggled', Callable(self, '_on_get_status').bind(Network.unit_fs_2))
    node_select_fs_2.get_node2(1, 7).connect('text_submitted', Callable(self, '_on_set_base_can_macro').bind(Network.unit_fs_2))
    node_select_fs_2.get_node2(1, 8).get_child(1, false).connect('toggled', Callable(self, '_on_status_can_macro').bind(Network.unit_fs_2))
    ## FS 3
    node_select_fs_3.get_node2(1, 2).connect('text_submitted', Callable(self, '_on_set_ferq_3'))
    node_select_fs_3.get_node2(1, 3).connect('text_submitted', Callable(self, '_on_set_att_3'))
    node_select_fs_3.get_node2(1, 4).connect('item_selected', Callable(self, '_on_modul_fs_3'))
    $TabContainer/PRD/body_grid/litera_1/fs_control.get_node2(1, 5).get_child(1, false).connect('toggled', Callable(self, '_on_get_status').bind(Network.unit_fs_3))
    node_select_fs_3.get_node2(1, 7).connect('text_submitted', Callable(self, '_on_set_base_can_macro_3'))
    node_select_fs_3.get_node2(1, 8).get_child(1, false).connect('toggled', Callable(self, '_on_status_can_macro_3'))

    Network.connect('yau_status_line', Callable(self, '_on_yau_status'))
    Network.connect('yau_receive', Callable(self, '_on_data_received'))
    Network.connect('yau_read_isa', Callable(self, '_on_read_isa'))
    #Network.connect('port_fs_opened', _on_port_changed.bind(Color.AQUAMARINE))
    #Network.connect('port_fs_closed', _on_port_changed.bind(Color.DARK_GRAY))
    #Network.connect('data_from_fs_1', _on_data_fs_1)
    #Network.connect('data_from_fs_2', _on_data_fs_2)
    #Network.connect('data_from_fs_3', _on_data_fs_3)
    Network.unit_fs_1.connect("connected", Callable(self, "_on_port_changed").bind(Network.unit_fs_1, Constants.STATE_VAL.GOOD))
    Network.unit_fs_1.connect("disconnected", Callable(self, "_on_port_changed").bind(Network.unit_fs_1, Constants.STATE_VAL.NONE))
    Network.unit_fs_1.connect("error_connect", Callable(self, "_on_port_changed").bind(Network.unit_fs_1, Constants.STATE_VAL.ERROR))
    Network.unit_fs_1.connect("data_fs", Callable(self, "_on_data_fs").bind(Network.unit_fs_1))

    Network.unit_fs_2.connect("connected", Callable(self, "_on_port_changed").bind(Network.unit_fs_2, Constants.STATE_VAL.GOOD))
    Network.unit_fs_2.connect("disconnected", Callable(self, "_on_port_changed").bind(Network.unit_fs_2, Constants.STATE_VAL.NONE))
    Network.unit_fs_2.connect("error_connect", Callable(self, "_on_port_changed").bind(Network.unit_fs_2, Constants.STATE_VAL.ERROR))
    Network.unit_fs_2.connect("data_fs", Callable(self, "_on_data_fs").bind(Network.unit_fs_2))

    self.add_child(timer_modul_um)
    timer_modul_um.connect('timeout', Callable(self, '_on_timer_modul_um'))
    timer_modul_um.wait_time = TIMER_BLOCK_EMS
    self.connect('write_ems_g_start', _on_write_ems_g)
    $Background/switch_panel/burgerButton.set_pressed_no_signal(true)
    _on_burger_button(true)


func add_signs_scene():
    # Таблица УКП-1
    node_select1.set_node_text(0, 0, 'Мощность')
    node_select1.set_node_text(1, 0, 'Температура')

    # Таблица УКП-2
    node_select2.set_node_text(0, 0, 'Мощность')
    node_select2.set_node_text(1, 0, 'Температура')

    # Таблица УКП-1
    node_select3.set_node_text(0, 0, 'Мощность')
    node_select3.set_node_text(1, 0, 'Температура')

    var item_place_yau_07: int = 9
    var item_place_fs_1: int = 18
    var item_place_fs_2: int = 28
    # Таблица ЯУ-07б-1
    node_select_yau_07b.set_node_text(0, 0, Constants.SIGNS[Constants.CURRENT_MODE][0]) # 'ПРД-Н'
    node_select_yau_07b.set_node_text(1, 0, Constants.SIGNS[Constants.CURRENT_MODE][1]) # 'Литера 2'
    node_select_yau_07b.set_node_text(0, 1, Constants.SIGNS[Constants.CURRENT_MODE][2]) # 'Запрет СИ 2'
    node_select_yau_07b.set_node_text(0, 2, Constants.SIGNS[Constants.CURRENT_MODE][3]) # 'Модуляция УМ'
    node_select_yau_07b.set_node_text(0, 3, Constants.SIGNS[Constants.CURRENT_MODE][4]) # 'Положение луча'
    node_select_yau_07b.set_node_text(0, 4, Constants.SIGNS[Constants.CURRENT_MODE][5]) # 'Аттенюатор УМ'
    node_select_yau_07b.get_node2(1, 5).get_child(1).visible = Constants.CURRENT_MODE != Constants.MODE.PRD_H
    node_select_yau_07b.set_node_text(0, 5, Constants.SIGNS[Constants.CURRENT_MODE][6])# 'ФГОЗ'
    node_select_yau_07b.set_node_text(0, 6, Constants.SIGNS[Constants.CURRENT_MODE][7]) # 'СИ 2 в УФ'
    node_select_yau_07b.set_node_text(0, 7, Constants.SIGNS[Constants.CURRENT_MODE][8]) # 'СЗИ 2 от УФ'

    # Таблица ЯУ-07б-2
    node_select_yau_07b_2.set_node_text(0, 0, Constants.SIGNS[Constants.CURRENT_MODE][item_place_yau_07+0])  # 'ПРД-Н'
    node_select_yau_07b_2.set_node_text(1, 0, Constants.SIGNS[Constants.CURRENT_MODE][item_place_yau_07+1])  # 'Литера 3',
    node_select_yau_07b_2.set_node_text(0, 1, Constants.SIGNS[Constants.CURRENT_MODE][item_place_yau_07+2]) # 'Запрет СИ 3'
    node_select_yau_07b_2.set_node_text(0, 2, Constants.SIGNS[Constants.CURRENT_MODE][item_place_yau_07+3]) # 'Модуляция УМ'
    node_select_yau_07b_2.set_node_text(0, 3, Constants.SIGNS[Constants.CURRENT_MODE][item_place_yau_07+4]) # 'Положение луча'
    node_select_yau_07b_2.set_node_text(0, 4, Constants.SIGNS[Constants.CURRENT_MODE][item_place_yau_07+5]) # 'Аттенюатор УМ'
    node_select_yau_07b_2.get_node2(1, 5).get_child(1).visible = Constants.CURRENT_MODE != Constants.MODE.PRD_K
    node_select_yau_07b_2.set_node_text(0, 5, Constants.SIGNS[Constants.CURRENT_MODE][item_place_yau_07+6]) # 'ФГОЗ 3'
    node_select_yau_07b_2.set_node_text(0, 6, Constants.SIGNS[Constants.CURRENT_MODE][item_place_yau_07+7]) # 'СИ 3 в УФ'
    node_select_yau_07b_2.set_node_text(0, 7, Constants.SIGNS[Constants.CURRENT_MODE][item_place_yau_07+8]) # 'СЗИ 3 от УФ'

    #Таблица ФС-1
    node_select_fs_1.set_node_text(0, 0, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_1+0]) # 'Модуль ФС'
    node_select_fs_1.set_node_text(1, 0, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_1+1]) # 'Литера 2'

    node_select_fs_1.set_node_text(0, 1, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_1+2]) # 'Состояние'
    node_select_fs_1.set_node_text(0, 2, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_1+3]) # 'Частота'
    node_select_fs_1.get_node2(1, 2).placeholder_text = 'в МГц'
    node_select_fs_1.get_node2(1, 2).editable = true
    node_select_fs_1.set_node_text(0, 3, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_1+4]) # 'Аттенюатор'
    node_select_fs_1.get_node2(1, 3).placeholder_text = 'в dB'
    node_select_fs_1.get_node2(1, 3).editable = true
    node_select_fs_1.set_node_text(0, 4, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_1+5]) # 'Модуляция'
    node_select_fs_1.set_node_text(0, 5, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_1+6]) # 'Генератор ФС'
    node_select_fs_1.set_node_text(0, 6, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_1+7]) # 'СИ 2 от ФС'
    node_select_fs_1.set_node_text(0, 7, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_1+8]) # 'Фильтр CAN'
    node_select_fs_1.get_node2(1, 7).placeholder_text = 'в МГц'
    node_select_fs_1.get_node2(1, 7).editable = true
    node_select_fs_1.set_node_text(0, 8, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_1+9]) # 'Статус CAN'

    #Таблица ФС-2
    node_select_fs_2.set_node_text(0, 0, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_2+0]) # 'Модуль ФС'
    node_select_fs_2.set_node_text(1, 0, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_2+1]) # 'Литера ФС'
    node_select_fs_2.set_node_text(0, 1, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_2+2]) # 'Состояние'
    node_select_fs_2.set_node_text(0, 2, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_2+3]) # 'Частота'
    node_select_fs_2.get_node2(1, 2).placeholder_text = 'в МГц'
    node_select_fs_2.get_node2(1, 2).editable = true
    node_select_fs_2.set_node_text(0, 3, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_2+4]) # 'Аттенюатор ФС'
    node_select_fs_2.get_node2(1, 3).placeholder_text = 'в dB'
    node_select_fs_2.get_node2(1, 3).editable = true
    node_select_fs_2.set_node_text(0, 4, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_2+5]) # 'Модуляция'
    node_select_fs_2.set_node_text(0, 5, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_2+6]) # 'Генератор ФС'
    node_select_fs_2.set_node_text(0, 6, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_2+7]) # 'СИ 3 от ФС'
    node_select_fs_2.set_node_text(0, 7, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_2+8]) # 'Фильтр CAN'
    node_select_fs_2.get_node2(1, 7).placeholder_text = 'в МГц'
    node_select_fs_2.get_node2(1, 7).editable = true
    node_select_fs_2.set_node_text(0, 8, Constants.SIGNS[Constants.CURRENT_MODE][item_place_fs_2+9]) # 'Статус CAN')

    $TabContainer/PRD/body_grid/litera_1.visible = Constants.CURRENT_MODE ==Constants.MODE.PRD_K
    node_select_yau_07b_2.get_node2(1, 4).clear()
    if Constants.CURRENT_MODE ==Constants.MODE.PRD_K:
        for key in Constants.ATT_DICT_correct:
            node_select_yau_07b_2.get_node2(1, 4).add_item(key)
    else:
        for key in Constants.ATT_DICT:
            node_select_yau_07b_2.get_node2(1, 4).add_item(key)


# Список статусов ячеек ЯУ-07б
func _on_yau_status(addr: String):
    var count_packets_await: int = 20
    var status_yau_list = $TabContainer/PRD/status_yau_list.get_children()
    var status_label = $TabContainer/PRD/status_yau
    if addr.is_empty():
        # Сброс состояния, если адрес пуст (нет связи)
        for label  in status_yau_list:
            label.text = ''
        status_label.modulate = Color.CRIMSON
        status_label.text = 'ЯУ-07Б: нет связи'
        modul_um = [0, 0, 0, 0]
        return
    status_label.text = '' # Убираем статус, если есть сигнал от ЯУ-07Б

    # Обновляем счетчики
    for i in Constants.ADDRESSES.size():
        var address_match = (Constants.ADDRESSES[i][1] == addr)
        receive_yau_counter[i] = 0 if address_match else (receive_yau_counter[i] + 1) & 0xFFF
    # Обновляем статусы элементов
    for i in status_yau_list.size():
        var label = status_yau_list[i]
        var address_info = Constants.ADDRESSES[i]

        label.text = address_info[0]
        label.modulate = Color.AQUAMARINE if receive_yau_counter[i] < count_packets_await else Color.DARK_GRAY  # Если счетчик >= count_packets_await, помечаем серым, иначе — аквамарином


func _on_read_isa(unit_isa_ports: Dictionary) -> void:
    isa_from_yau07b = unit_isa_ports
    var isa_data: Dictionary = {}
    for key in unit_isa_ports.keys():
        isa_data[key] = unit_isa_ports[key]

        if isa_data.has(Constants.BASE_PORTS.EMS_G+2):
            var tmp = isa_data[Constants.BASE_PORTS.EMS_G+2]
            isa_data.erase(Constants.BASE_PORTS.EMS_G+2)

            var found = false
            for i in range(Constants.EMS_G_PORT_DATA_HOLDER.size()):
                if Constants.EMS_G_PORT_DATA_HOLDER[i][0] == tmp:
                    Constants.EMS_G_PORT_DATA_HOLDER[i][1] = isa_data
                    found = true
                    break
            if not found:
                Constants.EMS_G_PORT_DATA_HOLDER.append([tmp, isa_data])

    $load_status_yau.value += 1
    if len(Constants.EMS_G_PORT_DATA_HOLDER) == 32:
        emit_signal('read_ems_g_finish')
        $load_status_yau.visible = false

    $TabContainer/EMS_G/load_boadr/win_load.material.set('shader_parameter/dot_color_end', Color(0.8, 0.5, 1.0, 1.0 - 0.05 * len(Constants.EMS_G_PORT_DATA_HOLDER)))

    if isa_data.has(Constants.BASE_PORTS.UG+0x6):
        if (isa_data[Constants.BASE_PORTS.UG+0x6] & 0x7) < 7:
            $TabContainer/PRD/body_grid/litera_2_4_6/yau07b_control.get_node2(1, 3).select(isa_data[Constants.BASE_PORTS.UG+0x6] & 0x7)
            $TabContainer/PRD/body_grid/litera_2_4_6/yau07b_control.get_node2(1, 4).select((isa_data[Constants.BASE_PORTS.UG+0x6] & 0x38)>> 3)
        $TabContainer/PRD/body_grid/litera_2_4_6/PSK/ray_1.material.set('shader_parameter/turn', 0.735 + 0.025 * (isa_data[Constants.BASE_PORTS.UG+0x6] & 0x7))
        $TabContainer/PRD/body_grid/litera_2_4_6/PSK/ray_1.material.set('shader_parameter/inner_radius', 0.8 - 0.01 * (isa_data[Constants.BASE_PORTS.UG+0x6] & 0x38))
    if isa_data.has(Constants.BASE_PORTS.UG+0x8):
        if (isa_data[Constants.BASE_PORTS.UG+8] & 0x7) < 7:
            $TabContainer/PRD/body_grid/litera_3_5_7/yau07b_control.get_node2(1, 3).select(isa_data[Constants.BASE_PORTS.UG+0x8] & 0x7)
            $TabContainer/PRD/body_grid/litera_3_5_7/yau07b_control.get_node2(1, 4).select((isa_data[Constants.BASE_PORTS.UG+0x8] & 0x38)>>3)
        $TabContainer/PRD/body_grid/litera_3_5_7/PSK2/ray_2.material.set('shader_parameter/turn', 0.735 + 0.025 * (isa_data[Constants.BASE_PORTS.UG+0x8] & 0x7))
        $TabContainer/PRD/body_grid/litera_3_5_7/PSK2/ray_2.material.set('shader_parameter/inner_radius', 0.8 - 0.01 * (isa_data[Constants.BASE_PORTS.UG+0x8] & 0x38))
    if isa_data.has(Constants.BASE_PORTS.UG+0xA):
        if (isa_data[Constants.BASE_PORTS.UG+0xA] & 0x7) < 8:
            $TabContainer/PRD/body_grid/litera_1/PSK3/ray_litera_1.material.set('shader_parameter/inner_radius', 0.8 - 0.01 * ((isa_data[Constants.BASE_PORTS.UG+0xA] & 0x7) * (isa_data[Constants.BASE_PORTS.UG+0xA] & 0x7)) )
            $TabContainer/PRD/body_grid/litera_1/yau07b_control.get_node2(1, 4).select(isa_data[Constants.BASE_PORTS.UG+0xA])

    for index in Constants.EMS_G_PORT_DATA_HOLDER.size():
        var tmp_device_mode = Constants.EMS_G_PORT_DATA_HOLDER[index][0]
        if tmp_device_mode == Constants.META.CI_1_B_UF:
            var data_dict = Constants.EMS_G_PORT_DATA_HOLDER[index][1]
            if Constants.BASE_PORTS.EMS_G+8 in data_dict:
                $TabContainer/PRD/body_grid/litera_1/yau07b_control.get_node2(1,1).get_child(1).set_pressed_no_signal(data_dict[Constants.BASE_PORTS.EMS_G+8] >> 14)
        if tmp_device_mode == Constants.META.CI_2_B_UF:
            var data_dict = Constants.EMS_G_PORT_DATA_HOLDER[index][1]
            if Constants.BASE_PORTS.EMS_G+8 in data_dict:
                $TabContainer/PRD/body_grid/litera_2_4_6/yau07b_control.get_node2(1,1).get_child(1).set_pressed_no_signal(data_dict[Constants.BASE_PORTS.EMS_G+8] >> 14)
        if tmp_device_mode == Constants.META.CI_3_B_UF:
            var data_dict = Constants.EMS_G_PORT_DATA_HOLDER[index][1]
            if Constants.BASE_PORTS.EMS_G+8 in data_dict:
                $TabContainer/PRD/body_grid/litera_3_5_7/yau07b_control.get_node2(1,1).get_child(1).set_pressed_no_signal(data_dict[Constants.BASE_PORTS.EMS_G+8] >> 14)
        if tmp_device_mode == Constants.META.MODUL_UM_1: ## Синхронизация с Модуляцией УМ лиетры 1
            var data_dict = Constants.EMS_G_PORT_DATA_HOLDER[index][1]
            if Constants.BASE_PORTS.EMS_G+8 in data_dict:
                var select = data_dict[Constants.BASE_PORTS.EMS_G+8] >> 13 if data_dict[Constants.BASE_PORTS.EMS_G+8] >> 13 < 3 else 3
                $TabContainer/PRD/body_grid/litera_1/yau07b_control.get_node2(1,2).select(select)
                if select == 1:
                    $TabContainer/PRD/body_grid/litera_1/PSK3/ray_litera_1.material.set('shader_parameter/color_signal', Color.RED)
                else:
                    $TabContainer/PRD/body_grid/litera_1/PSK3/ray_litera_1.material.set('shader_parameter/color_signal', Color.DARK_ORANGE)
        if tmp_device_mode == Constants.META.MODUL_UM_2: ## Синхронизация с Модуляцией УМ лиетры 2, 4, 6
            var data_dict = Constants.EMS_G_PORT_DATA_HOLDER[index][1]
            if Constants.BASE_PORTS.EMS_G+8 in data_dict:
                var select = data_dict[Constants.BASE_PORTS.EMS_G+8] >> 13 if data_dict[Constants.BASE_PORTS.EMS_G+8] >> 13 < 3 else 3
                $TabContainer/PRD/body_grid/litera_2_4_6/yau07b_control.get_node2(1,2).select(select)
                if select == 3:
                    $TabContainer/PRD/body_grid/litera_2_4_6/PSK/ray_1.material.set('shader_parameter/color_signal', Color.RED)
                else:
                    $TabContainer/PRD/body_grid/litera_2_4_6/PSK/ray_1.material.set('shader_parameter/color_signal', Color.DARK_ORANGE)
        if tmp_device_mode == Constants.META.MODUL_UM_3: ## Синхронизация с Модуляцией УМ лиетры 3, 5, 7
            var data_dict = Constants.EMS_G_PORT_DATA_HOLDER[index][1]
            if Constants.BASE_PORTS.EMS_G+8 in data_dict:
                var select = data_dict[Constants.BASE_PORTS.EMS_G+8] >> 13 if data_dict[Constants.BASE_PORTS.EMS_G+8] >> 13 < 3 else 3
                $TabContainer/PRD/body_grid/litera_3_5_7/yau07b_control.get_node2(1,2).select(select)
                if select == 3:
                    $TabContainer/PRD/body_grid/litera_3_5_7/PSK2/ray_2.material.set('shader_parameter/color_signal', Color.RED)
                else:
                    $TabContainer/PRD/body_grid/litera_3_5_7/PSK2/ray_2.material.set('shader_parameter/color_signal', Color.DARK_ORANGE)
        if tmp_device_mode == Constants.META.FGOZ_4:
            var data_dict = Constants.EMS_G_PORT_DATA_HOLDER[index][1]
            if Constants.BASE_PORTS.EMS_G+8 in data_dict:
                $TabContainer/PRD/body_grid/litera_2_4_6/yau07b_control.get_node2(1,5).get_child(1).set_pressed_no_signal(data_dict[Constants.BASE_PORTS.EMS_G+8] >> 15)
        if tmp_device_mode == Constants.META.FGOZ_3:
            var data_dict = Constants.EMS_G_PORT_DATA_HOLDER[index][1]
            if Constants.BASE_PORTS.EMS_G+8 in data_dict:
                $TabContainer/PRD/body_grid/litera_3_5_7/yau07b_control.get_node2(1,5).get_child(1).set_pressed_no_signal(data_dict[Constants.BASE_PORTS.EMS_G+8] >> 15)


## Процесс обработки данных от модулей ФС в таблице
func _on_data_fs(fs_data: PackedByteArray, unit_fs_client: Node):
    var GRP = fs_data.decode_u8(0x0)
    var CMD = fs_data.decode_u8(0x1)
    var node_select
    var ray_node_path
    var fs_control_node_path

    var fs_number = 1 if unit_fs_client == Network.unit_fs_1 else 2 if unit_fs_client == Network.unit_fs_2 else 3
    match fs_number:
        1:
            node_select = node_select_fs_1
            ray_node_path = $TabContainer/PRD/body_grid/litera_2_4_6/PSK/ray_1
            fs_control_node_path = $TabContainer/PRD/body_grid/litera_2_4_6/fs_control
        2:
            node_select = node_select_fs_2
            ray_node_path = $TabContainer/PRD/body_grid/litera_3_5_7/PSK2/ray_2
            fs_control_node_path = $TabContainer/PRD/body_grid/litera_3_5_7/fs_control
        3:
            pass
    match CMD:
        Constants.CMD.READ_CARRIER:
            if GRP == Constants.GROUP.BASE:
                var freq = int(fs_data.decode_u64(0xC) / 1_000_000.0)
                node_select.set_node_text(2, 2, str(freq) + ' МГц')
                match fs_number:
                    1: freq_fs_1 = freq
                    2: freq_fs_2 = freq
                    3: freq_fs_3 = freq

        Constants.CMD.READ_ATT:
            if GRP == Constants.GROUP.RF:
                var att = fs_data.decode_float(0x18)
                node_select.set_node_text(2, 3, str(att) + ' dB')
                match fs_number:
                    1: att_fs_1 = att
                    2: att_fs_2 = att
                    3: att_fs_3 = att

        Constants.CMD.READ_GEN_STATUS:
            if GRP == Constants.GROUP.GENERATOR:
                if fs_data.decode_u32(0xC) == 0:
                    node_select.set_node_text(2, 5, 'Включен')
                    node_select.get_node2(2, 5).modulate = Color.AQUAMARINE
                    ray_node_path.material.set('shader_parameter/speed', 2.5)
                    fs_control_node_path.get_node2(1, 5).get_child(1).set_pressed_no_signal(true)
                else:
                    node_select.set_node_text(2, 5, 'Отключен')
                    node_select.get_node2(2, 5).modulate = Color.CRIMSON
                    ray_node_path.material.set('shader_parameter/speed', 0.0)
                    fs_control_node_path.get_node2(1, 5).get_child(1).set_pressed_no_signal(false)

        Constants.CMD.BASE_GET_CURRENT_TEMP:
            if GRP == Constants.GROUP.BASE:
                node_select.set_node_text(2, 0, '%.2f' % fs_data.decode_float(0xC) + ' °C')
        Constants.CMD.BASE_CAN_MACRO_READ:
            if GRP == Constants.GROUP.BASE:
                node_select.set_node_text(2, 7, str(fs_data.decode_u16(0x20)) + ' МГц')


func _process(_delta: float) -> void:
    # FS 1
    var node_freq_fs_1 = node_select_fs_1.get_node2(1, 2).get_text()
    var node_freq_fs_1_mod = node_select_fs_1.get_node2(0, 2)
    if (int(node_freq_fs_1) != freq_fs_1) and node_freq_fs_1 != '':
        node_freq_fs_1_mod.modulate = Color.AQUAMARINE
        node_freq_fs_1_mod.text = 'Частота*'
    else:
        node_freq_fs_1_mod.modulate = Color(1, 1, 0.941, 1)
        node_freq_fs_1_mod.text = 'Частота'
    node_freq_fs_1 = node_select_fs_1.get_node2(1, 3)
    node_freq_fs_1_mod = node_select_fs_1.get_node2(0, 3)
    if (int(node_freq_fs_1.get_text()) != att_fs_1) and node_freq_fs_1.get_text() != '':
        node_freq_fs_1_mod.modulate = Color.AQUAMARINE
        node_freq_fs_1_mod.text = 'Аттенюатор*'
    else:
        node_freq_fs_1_mod.modulate = Color(1, 1, 0.941, 1)
        node_freq_fs_1_mod.text = 'Аттенюатор'

    # FS 2
    var node_freq_fs_2 = node_select_fs_2.get_node2(1, 2)
    var node_freq_fs_2_mod = node_select_fs_2.get_node2(0, 2)
    if int(node_freq_fs_2.get_text()) != freq_fs_2 and node_freq_fs_2.get_text() != '':
        node_freq_fs_2_mod.modulate = Color.AQUAMARINE
        node_freq_fs_2_mod.text = 'Частота*'
    else:
        node_freq_fs_2_mod.modulate = Color(1, 1, 0.941, 1)
        node_freq_fs_2_mod.text = 'Частота'
    node_freq_fs_2 = node_select_fs_2.get_node2(1, 3)
    node_freq_fs_2_mod = node_select_fs_2.get_node2(0, 3)
    if int(node_freq_fs_2.get_text()) != att_fs_2 and node_freq_fs_2.get_text() != '':
        node_freq_fs_2_mod.modulate = Color.AQUAMARINE
        node_freq_fs_2_mod.text = 'Аттенюатор*'
    else:
        node_freq_fs_2_mod.modulate = Color(1, 1, 0.941, 1)
        node_freq_fs_2_mod.text = 'Аттенюатор'


## Рисует таблицу
func draw_tabl(tbl: Node, row: Array, count_row: int):
    for i_row in count_row:
        tbl.add_row(row[i_row])


func _on_data_received(data_from_yau_07):
    ## УКП
    for i in range(6): ## Мощность от УКП_1
        var power_ukp_1 = data_from_yau_07.decode_u16(Constants.DataIndices.POWER_UKP_1 + 2 * i)
        node_select1.set_node_text(0, i+1, '%d' % power_ukp_1)

    for i in range(6): ## Температура от УКП_1
        var temperature_ukp_1 = data_from_yau_07.decode_u16(Constants.DataIndices.TEMPERATURE_UKP_1 + 2 * i)
        var TMP = Constants.CONST_MIN_TEMP + (Constants.MAXIMUM_CODE_ADC - temperature_ukp_1) * Constants.TEMP + 3
        node_select1.set_node_text(1, i+1, '%d °С' % TMP)

    for i_pow in range(6): ## Мощность от УКП_2
        if len(data_from_yau_07) > Constants.DataIndices.POWER_UKP_2 + 2 * i_pow:
            var power_ukp_2 = data_from_yau_07.decode_u16(Constants.DataIndices.POWER_UKP_2 + 2 * i_pow)
            node_select2.set_node_text(0, i_pow+1, '%d' % power_ukp_2)

    for row in range(6): ## Температура от УКП_2
        if len(data_from_yau_07) > Constants.DataIndices.TEMPERATURE_UKP_2 + 2 * row:
            var temperature_ukp_2 = data_from_yau_07.decode_u16(Constants.DataIndices.TEMPERATURE_UKP_2 + 2 * row)
            var TMP = Constants.CONST_MIN_TEMP + (Constants.MAXIMUM_CODE_ADC - temperature_ukp_2) * Constants.TEMP + 3
            node_select2.set_node_text(1, row+1, '%d °С' % TMP)

    if len(data_from_yau_07) > Constants.DataIndices.TEMPERATURE_UKP_1 + 2 * 7:
        var power_ukp_3 = data_from_yau_07.decode_u16(Constants.DataIndices.POWER_UKP_1 + 2 * 7)
        var temperature_ukp_3 = data_from_yau_07.decode_u16(Constants.DataIndices.TEMPERATURE_UKP_1 + 2 * 7)
        var TMP = Constants.CONST_MIN_TEMP + (Constants.MAXIMUM_CODE_ADC - temperature_ukp_3) * Constants.TEMP + 3
        node_select3.set_node_text(0, 1, '%d' % power_ukp_3)
        node_select3.set_node_text(1,1, '%d °С' % TMP)


func set_frame(node: Node, val: int): node.set_frame(val)


func _on_save_config():
    var file_dialog = FileDialog.new()
    file_dialog.access = FileDialog.ACCESS_USERDATA
    file_dialog.title = "Сохранить файл как"
    file_dialog.set_size(Vector2(600, 400))
    file_dialog.mode = FileDialog.FILE_MODE_SAVE_FILE
    file_dialog.current_dir = 'user://saves'
    file_dialog.connect("file_selected", Callable(self, "_save_selected_file"))
    add_child(file_dialog)
    file_dialog.popup_centered()


func _save_selected_file(file_path: String):
    var data = Constants.EMS_G_PORT_DATA_HOLDER
    var param_ems_g: Dictionary = {}
    # Формируем словари
    for item in data:
        var regist: Dictionary = {}
        regist[0x122] = item[0]
        for key in item[1]:
            if key in need_port:
                regist[key] = item[1][key]
        param_ems_g[item[0]] = regist
    # Сохранение данных ЭМС-Г
    var file = FileAccess.open(file_path, FileAccess.WRITE)
    if file != null:
        file.store_string(JSON.stringify(param_ems_g))
        file.close()
        $Background/notice/load_notice.text = '✅ Файл %s записан успешно!' % ProjectSettings.globalize_path(file_path)
        $Background/notice/load_notice.visible = true
        await get_tree().create_timer(2.0).timeout
        $Background/notice/load_notice.visible = false


func _on_load_config():
    var file_dialog = FileDialog.new()
    file_dialog.access = FileDialog.ACCESS_USERDATA
    file_dialog.set_title("Выберите файл")
    file_dialog.set_size(Vector2(600, 400))
    file_dialog.mode = FileDialog.FILE_MODE_OPEN_FILE

    file_dialog.current_dir = 'user://saves'
    file_dialog.connect("file_selected", Callable(self, "_load_selected_file"))
    add_child(file_dialog)
    file_dialog.popup_centered()


func _load_selected_file(file_path: String):
    var file = FileAccess.open(file_path, FileAccess.READ)
    # Проверка на открытие/чтение файла
    if file == null:
        return
    var file_content: String = file.get_as_text()
    file.close()

    var json: JSON = JSON.new()
    var error = json.parse(file_content)
    if error == OK:
        var data_received: Dictionary = json.data
        if typeof(data_received) == TYPE_DICTIONARY:
            $Background/notice/load_notice.text = '✅ Файл %s прочитан успешно' % file_path
            $Background/notice/load_notice.visible = true
            emit_signal('write_ems_g_start', data_received)
            await get_tree().create_timer(2.0).timeout
            $Background/notice/load_notice.visible = false
        else:
            print_debug("Несоответствующий тип данных!")
    else:
        print_debug("JSON Parse Error: ", json.get_error_message(), " in ", file_content, " at line ", json.get_error_line())


func _on_write_ems_g(data_to_ems_g: Dictionary):
    for key in data_to_ems_g.keys():
        if int(key) < 17:
            Network.write_port_isa(Constants.BASE_PORTS.EMS_G+2, data_to_ems_g[key][str(Constants.BASE_PORTS.EMS_G+0x2)])
            Network.write_port_isa(Constants.BASE_PORTS.EMS_G+0xA, data_to_ems_g[key][str(Constants.BASE_PORTS.EMS_G+0xA)])
        if int(key) > 46:
            Network.write_port_isa(Constants.BASE_PORTS.EMS_G+2, data_to_ems_g[key][str(Constants.BASE_PORTS.EMS_G+0x2)])
            Network.write_port_isa(Constants.BASE_PORTS.EMS_G+4, data_to_ems_g[key][str(Constants.BASE_PORTS.EMS_G+0x8)])
            Network.write_port_isa(Constants.BASE_PORTS.EMS_G+4, data_to_ems_g[key][str(Constants.BASE_PORTS.EMS_G+0x4)])


func on_mode_select(intem_from_sector: int) -> void:
    var pribor_selec: String = Constants.ADDRESSES[intem_from_sector][0]
    var node_select_device: GDTable = $TabContainer/PRD/select_dev
    var get_select_device: Node = node_select_device.get_node2(1, 0)
    var meta: Array = get_select_device.get_item_metadata(intem_from_sector)
    Constants.CURRENT_MODE = meta[2]
    add_signs_scene()
    Network.on_command_change_device(meta)
    Network.read_port_isa([Constants.BASE_PORTS.UG+8, Constants.BASE_PORTS.UG+6, Constants.BASE_PORTS.UG+0xA])
    $load_status_yau.value = 0
    emit_signal('read_ems_g_start')
    $load_status_yau.visible = true
    _load_selected_file('user://saves/' + pribor_selec)


func _on_zapret_1(toggled_on: bool) -> void:
    var meta = Constants.META.CI_1_B_UF
    Network.write_port_isa(Constants.BASE_PORTS.EMS_G+2, meta)
    var zapret_mode = 0x4000 if toggled_on else 0x0
    Network.write_port_isa(Constants.BASE_PORTS.EMS_G+8, zapret_mode)


func _on_zapret_2(toggled_on: bool) -> void:
    var meta = Constants.META.CI_2_B_UF
    Network.write_port_isa(Constants.BASE_PORTS.EMS_G+2, meta)
    var zapret_mode = 0x4000 if toggled_on else 0x0
    Network.write_port_isa(Constants.BASE_PORTS.EMS_G+8, zapret_mode)


func _on_zapret_3(toggled_on: bool) -> void:
    var meta = Constants.META.CI_3_B_UF
    Network.write_port_isa(Constants.BASE_PORTS.EMS_G+2, meta)
    var zapret_mode = 0x4000 if toggled_on else 0x0
    Network.write_port_isa(Constants.BASE_PORTS.EMS_G+8, zapret_mode)


func _on_modul_um(item_from_ray_1: int, node: Node):
    var modul_um_values = {
        1: 0x2000,
        2: 0x4000,
        3: 0x8000,
    }
    var meta_mapping = {
        Constants.META.MODUL_UM_1: 0,
        Constants.META.MODUL_UM_2: 1,
        Constants.META.MODUL_UM_3: 2,
    }
    var meta_key = node.get_meta('meta_um')
    var index = meta_mapping.get(meta_key, -1)

    if index != -1:
        current_meta[index] = meta_key
        modul_um[index] = modul_um_values.get(item_from_ray_1, 0)

        Network.write_port_isa(Constants.BASE_PORTS.EMS_G + 2, current_meta[index])
        Network.write_port_isa(Constants.BASE_PORTS.EMS_G + 8, modul_um[index])
        Network.read_port_isa([Constants.BASE_PORTS.EMS_G+8])
    else:
        return


## Таймер для модуляции УМ
func _on_timer_modul_um():
    const DATA_FOR_UNBLOCK_EMS: int = 6666
    Network.write_port_isa(Constants.BASE_PORTS.EMS_G, DATA_FOR_UNBLOCK_EMS)


## Включение/отключение сигнала ФГОЗ
func _on_fgos_1(toggled_on: bool):
    var meta = Constants.META.FGOZ_4
    Network.write_port_isa(Constants.BASE_PORTS.EMS_G+2, meta)
    var fgos_um = 0x8000 if toggled_on else 0x0
    Network.write_port_isa(Constants.BASE_PORTS.EMS_G+8, fgos_um)


## Включение/отключение сигнала ФГОЗ
func _on_fgos_2(toggled_on: bool):
    var meta = Constants.META.FGOZ_3
    Network.write_port_isa(Constants.BASE_PORTS.EMS_G+2, meta)
    var fgos_um = 0x8000 if toggled_on else 0x0
    Network.write_port_isa(Constants.BASE_PORTS.EMS_G+8, fgos_um)


## Регулировка положением луча 1
func _on_btn_ray_1(item_from_ray_1: int) -> void:
    if isa_from_yau07b.has(Constants.BASE_PORTS.UG+6):
        var mask = 0x7
        Network.write_port_isa(Constants.BASE_PORTS.UG+6, set_bits(isa_from_yau07b[Constants.BASE_PORTS.UG+6], item_from_ray_1, mask))
        Network.read_port_isa([Constants.BASE_PORTS.UG+6])
    else:
        print_debug('В ISA отсутствует данные в \"%x\" порту' % (Constants.BASE_PORTS.UG+0x6))


## Регулировка положением луча 2
func _on_btn_ray_2(item_from_ray_2: int) -> void:
    if isa_from_yau07b.has(Constants.BASE_PORTS.UG+8):
        var mask = 0x7
        Network.write_port_isa(Constants.BASE_PORTS.UG+8, set_bits(isa_from_yau07b[Constants.BASE_PORTS.UG+8], item_from_ray_2, mask))
        Network.read_port_isa([Constants.BASE_PORTS.UG+8])
    else:
        print_debug('В ISA отсутствует данные в \"%x\" порту' % (Constants.BASE_PORTS.UG+0x8))


## Регулировка аттенюатора луча 1
func _on_attenuator_1(item_from_att_1: int) -> void:
    if isa_from_yau07b.has(Constants.BASE_PORTS.UG+6):
        var mask = 0x38
        Network.write_port_isa(Constants.BASE_PORTS.UG+6, set_bits(isa_from_yau07b[Constants.BASE_PORTS.UG+6], item_from_att_1 << 3, mask))
        Network.read_port_isa([Constants.BASE_PORTS.UG+6])
    else:
        print_debug('В ISA отсутствует данные в \"%x\" порту' % (Constants.BASE_PORTS.UG+0x6))


## Регулировка аттенюатора луча 2
func _on_attenuator_2(item_from_att_1: int) -> void:
    if isa_from_yau07b.has(Constants.BASE_PORTS.UG+8):
        var mask = 0x38
        Network.write_port_isa(Constants.BASE_PORTS.UG+8, set_bits(isa_from_yau07b[Constants.BASE_PORTS.UG+8], item_from_att_1 << 3, mask))
        Network.read_port_isa([Constants.BASE_PORTS.UG+8])
    else:
        print_debug('В ISA отсутствует данные в \"%x\" порту' % (Constants.BASE_PORTS.UG+0x8))


## Регулировка аттенюатора луча 3
func _on_attenuator_3(item_from_att_1: int) -> void:
    if isa_from_yau07b.has(Constants.BASE_PORTS.UG+0xA):
        var mask = 0x7
        Network.write_port_isa(Constants.BASE_PORTS.UG+0xA, set_bits(isa_from_yau07b[Constants.BASE_PORTS.UG+0xA], item_from_att_1, mask))
        Network.read_port_isa([Constants.BASE_PORTS.UG+0xA])
    else:
        print_debug('В ISA отсутствует данные в \"%x\" порту' % (Constants.BASE_PORTS.UG+0xA))


## Устанавливает биты в соответствии с маской
## [param v] - Прежние значения бит
## [param a] - Новые значения бит
## [param m] - Маска изменяемых бит
func set_bits(v, a, m):
    return (~m) & v | a & m


## ФС Connect close
func _on_port_changed(client_addr: String, unit_fs_client: Node, status) -> void:
    var loging = 'Соединение ...' if status == Constants.STATE_VAL.NONE else 'Подключено' if status == Constants.STATE_VAL.GOOD else 'Ошибка'
    var color = Color.AQUAMARINE if status == Constants.STATE_VAL.GOOD else Color.DARK_GRAY if status == Constants.STATE_VAL.NONE else Color.CRIMSON

    if unit_fs_client == Network.unit_fs_1:
        $TabContainer/PRD/body_grid/litera_2_4_6/fs_control.set_node_text(1, 1, client_addr)
        $TabContainer/PRD/body_grid/litera_2_4_6/fs_control.set_node_text(2, 1, loging)
        $TabContainer/PRD/body_grid/litera_2_4_6/fs_control.get_node2(1,1).modulate = color
    elif unit_fs_client == Network.unit_fs_2:
        $TabContainer/PRD/body_grid/litera_3_5_7/fs_control.set_node_text(1, 1, client_addr)
        $TabContainer/PRD/body_grid/litera_3_5_7/fs_control.set_node_text(2, 1, loging)
        $TabContainer/PRD/body_grid/litera_3_5_7/fs_control.get_node2(1,1).modulate = color
    elif unit_fs_client == Network.unit_fs_3:
        $TabContainer/PRD/body_grid/litera_1/fs_control.set_node_text(1, 1, client_addr)
        $TabContainer/PRD/body_grid/litera_1/fs_control.set_node_text(2, 1, loging)
        $TabContainer/PRD/body_grid/litera_1/fs_control.get_node2(1,1).modulate = color


# Установка формы сигнала (модуляция константа или msk)
func _on_modul_fs(modulation_select_1: int, unit_fs_client: Node) -> void:
    if modulation_select_1 == 0:
        unit_fs_client.set_configure_state_msk_const()
    elif modulation_select_1 == 1:
        unit_fs_client.set_configure_state_msk_modul_1()


# Установка и получение статуса генератора фс
func _on_get_status(toggled_btn: bool, unit_fs_client: Node):
    if $Background/switch_panel/select_prd.is_pressed() or $Background/switch_panel/texture_prd.is_pressed():
        var inverted_state = not toggled_btn
        unit_fs_client.set_gen_state(inverted_state)
        unit_fs_client.get_gen_state()
        unit_fs_client.get_base_current_temp()


func _on_set_ferq(freq: String, unit_fs_client: Node):
    # Проверка на наличие символов в строке freq
    var regex = RegEx.new()
    regex.compile("^[0-9]+$")
    if not regex.search(freq):
        print_debug('Ошибка: частота должна быть числом без букв')
        return
    # Преобразование строки в число
    var freq_int = int(freq) * 1_000_000

    # Проверка на диапазон
    if freq_int < 370 * 1_000_000 or freq_int > 6100 * 1_000_000:
        print_debug('Некорректная частота')
        return

    unit_fs_client.set_carrier(freq_int)
    unit_fs_client.get_carrier()


func _on_set_att(att: String, unit_fs_client: Node):
    unit_fs_client.set_att_batch(float(att))
    if unit_fs_client == Network.unit_fs_1:
        save_settings(float(att), 0)
    elif unit_fs_client == Network.unit_fs_2:
        save_settings(float(att), 1)
    elif unit_fs_client == Network.unit_fs_3:
        save_settings(float(att), 2)
    unit_fs_client.get_att_batch()


func _on_set_base_can_macro(can_freq: String, unit_fs_client: Node):
    unit_fs_client.set_base_can_macro(int(can_freq))
    unit_fs_client.get_base_can_macro()


func _on_status_can_macro(toggled_btn: bool, unit_fs_client: Node):
    unit_fs_client.status_can_macro_exec(toggled_btn)


## Switch panel
func _on_prd_select() -> void:
    $load_status_yau.value = 0
    emit_signal('read_ems_g_start')
    set_tab_and_buttons(0, 'select_prd', 'texture_prd')
    Network.unit_fs_1.get_gen_state()
    Network.unit_fs_2.get_gen_state()


func _on_control_button() -> void:
    $TabContainer/ControlPanel._on_start_super_control()
    set_tab_and_buttons(1, 'select_control', 'texture_control')


func _on_emsg_select() -> void:
    $load_status_yau.value = 0
    emit_signal('read_ems_g_start')
    set_tab_and_buttons(2, 'select_ems_g', 'texture_ems_g')


func _on_mfs_select() -> void:
    set_tab_and_buttons(3, 'select_fs', 'texture_fs')


func _on_burger_button(toggled_on: bool) -> void:
    var txt_grp: Array = get_tree().get_nodes_in_group('burger_gr')
    var select_grp: Array = get_tree().get_nodes_in_group('select_grp')
    var tween: Tween = get_tree().create_tween()
    var pos_on_select: int = 17
    var pos_on_txt: int = 15
    var temp = txt_grp
    var tmp_pos = pos_on_txt
    var pos_off: int = -300
    var panel = $Background/switch_panel
    if toggled_on:
        tween.tween_property($Background/switch_panel/burgerButton/block, "global_position", Vector2(180, $Background/switch_panel/burgerButton/block.global_position.y), 0.1).set_trans(Tween.TRANS_LINEAR).set_ease(Tween.EASE_OUT)
        temp = select_grp
    else:
        tween.tween_property($Background/switch_panel/burgerButton/block, "global_position", Vector2(10, $Background/switch_panel/burgerButton/block.global_position.y), 0.1).set_trans(Tween.TRANS_LINEAR).set_ease(Tween.EASE_OUT)

    for btn in temp:
        tween.tween_property(btn, "global_position", Vector2(pos_off, btn.global_position.y), 0.1).set_trans(Tween.TRANS_QUINT).set_ease(Tween.EASE_OUT)

    if toggled_on:
        # Анимация вправо
        tween.tween_property(panel, "global_position", Vector2(-170, panel.global_position.y), 0.3).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)
    else:
        # Анимация влево
        tween.tween_property(panel, "global_position", Vector2(0, panel.global_position.y), 0.3).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)

    temp = txt_grp if toggled_on else select_grp
    tmp_pos = pos_on_txt if toggled_on else pos_on_select

    for btn in temp:
        tween.tween_property(btn, "global_position", Vector2(tmp_pos, btn.global_position.y), 0.1).set_trans(Tween.TRANS_QUINT).set_ease(Tween.EASE_OUT)

    tween.tween_property($Background/switch_panel/burgerButton/block, "global_position", Vector2(-90, $Background/switch_panel/burgerButton/block.global_position.y), 0.1).set_trans(Tween.TRANS_LINEAR).set_ease(Tween.EASE_OUT)


func set_tab_and_buttons(tab_index: int, button_name: String, txt_button_name: String) -> void:
    $TabContainer.current_tab = tab_index
    var switch_panel = $Background/switch_panel

    for button in switch_panel.get_children():
        if button is Button or TextureButton:
            if button.name != 'burgerButton':
                button.set_pressed_no_signal(button.name == button_name or button.name == txt_button_name)
            if button.name == 'select_control' or button.name == 'texture_control':
                if button_name == 'select_control' or button_name == 'texture_control':
                    $load_status_yau.visible = false
                else:
                    $load_status_yau.visible = true


func _on_connect_prd_pressed() -> void:
    var pribor_selec: int = $TabContainer/PRD/select_dev.get_node2(1, 0).get_selected_id()
    on_mode_select(pribor_selec)


func save_settings(to_att_change: float, mode: int):
    if Constants.ADDRESSES[$TabContainer/PRD/select_dev.get_node2(1, 0).get_selected_id()][0] in Constants.FS_ATT:
        var read_temp = Constants.FS_ATT[Constants.ADDRESSES[$TabContainer/PRD/select_dev.get_node2(1, 0).get_selected_id()][0]]
        read_temp[mode] = to_att_change
        Constants.FS_ATT[Constants.ADDRESSES[$TabContainer/PRD/select_dev.get_node2(1, 0).get_selected_id()][0]] = read_temp
    else:
        return
    var file = FileAccess.open("user://saves/fs_setting", FileAccess.WRITE)
    if file:
        file.store_var(Constants.FS_ATT)
        file.close()

    Constants.read_file()


func on_ems_block(toggled_on: bool) -> void:
    if toggled_on:
        timer_modul_um.start()
    else:
        timer_modul_um.stop()
