extends Panel
signal signal_FS_is_ready()

var node_select1: Node
var shift: int = 2
var button_link_meta: Dictionary = {}
var status_fs_1
var status_fs_2
var status_fs_3
var CI_1_UF: Node
var CI_2_UF:  Node
var CI_3_UF:  Node
var CZI_1_FS: Node
var CZI_2_FS: Node
var CZI_3_FS: Node
var CZI_4_FS: Node
var CZI_5_FS: Node
var CZI_6_FS: Node
var CZI_7_FS: Node
var CI_2_FS:  Node
var CI_3_FS:  Node
var CI_4_FS:  Node
var CI_5_FS:  Node
var CI_1_FS:  Node
var CI_6_FS:  Node
var CI_7_FS:  Node


func _on_read_ems_g():
    $load_boadr.visible = true
    Constants.EMS_G_PORT_DATA_HOLDER.clear()
    for i_input in 16:
        Network.write_port_isa(Constants.BASE_PORTS.EMS_G+2, 1+i_input)
        Network.read_port_isa([Constants.BASE_PORTS.EMS_G+0xA])

    for i_output in range(46, 62):
        Network.write_port_isa(Constants.BASE_PORTS.EMS_G+2, 1+i_output)
        Network.read_port_isa([Constants.BASE_PORTS.EMS_G+4, Constants.BASE_PORTS.EMS_G+8])


func _on_sync():
    if not get_parent().get_parent().get_child(0).get_child(1).get_child(2).is_pressed() or not $load_boadr.is_visible_in_tree():
        return

    for index in 16:
        for row in 16:
            var chk_btn = node_select1.get_node2(index+2, row+3).get_child(1, false)
            chk_btn.set_pressed_no_signal(false)

    for index in 32:
        var tmp_device_mode = Constants.EMS_G_PORT_DATA_HOLDER[index][0]
        if tmp_device_mode > 46:
            var port0x124: int
            var port0x128: int
            for key in Constants.EMS_G_PORT_DATA_HOLDER[index][1].keys():
                if key == 0x124:
                    port0x124 = Constants.EMS_G_PORT_DATA_HOLDER[index][1][key]
                    for row in 16:
                        if (port0x124 & (1 << row)) != 0:
                            var chk_btn = node_select1.get_node2(tmp_device_mode-45, row+3).get_child(1, false)
                            chk_btn.set_pressed_no_signal(true)
                if key == 0x128:
                    port0x128 = Constants.EMS_G_PORT_DATA_HOLDER[index][1][key]
                    var list = node_select1.get_node2(tmp_device_mode-45, 0)
                    var select = 0 if port0x128 == 0 else 1 if port0x128 == 0x2000 else 2 if port0x128 == 0x4000 else 3
                    list.select(select)
    $load_boadr.visible = false


func _ready() -> void:
    node_select1 = $table1
    var EMS_G_TABLE: Array
    for i_row in Constants.INPUT_EMS_G.size() + shift + 1:
        var column: Array
        for out_colum in Constants.OUT_EMS_G.size()+shift:
            if  out_colum > 1 and i_row ==0:
                column.append(Constants.TableList)
            elif out_colum > 1 and i_row > 2:
                column.append(Constants.Switch)
            elif (out_colum == 1 and i_row > 2) or (out_colum > 1 and i_row == 2):
                column.append(Constants.SocketStatus)
            else:
                column.append(Constants.TableNode)
        EMS_G_TABLE.append(column)

    draw_tabl(node_select1, EMS_G_TABLE, EMS_G_TABLE.size())

    node_select1.get_node2(1, 1).text = 'x3_ВЫХ:GND'
    node_select1.get_node2(0, 2).text = 'x3_ВХ :GND'
    for i in Constants.INPUT_EMS_G.size():
        node_select1.get_node2(0, i+shift+1).text = Constants.INPUT_EMS_G[i]

    for i in Constants.OUT_EMS_G.size():
        node_select1.get_node2(i+shift, 1).text = Constants.OUT_EMS_G[i][1]

    for i in EMS_G_TABLE[0].size()-shift:
        var list = node_select1.get_node2(i+shift, 0)
        list.set_meta('device', Constants.OUT_EMS_G[i][0])
        list.connect('item_selected', Callable(self, 'on_mode_link').bind(list))
        for k in Constants.OUT_x128.size():
            list.add_item(Constants.OUT_x128[k])

    var columns_min_size: Array
    for i in EMS_G_TABLE[0].size():
        if i < 2:
            columns_min_size.append(110)
        else:
            columns_min_size.append(80)
    node_select1.set_columns_min_size(columns_min_size)

    var parrent_NODE2 = get_parent().get_parent()
    parrent_NODE2.connect('read_ems_g_start', Callable(self, '_on_read_ems_g'))
    parrent_NODE2.connect('read_ems_g_finish', Callable(self, '_on_sync'))

    Network.connect('yau_receive', Callable(self, '_on_data_received'))
    create_link_button(node_select1, shift+1, 16+shift+1, shift, 16+shift)


func draw_tabl(tbl, 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):
    var in_blank: int = data_from_yau_07.decode_u16(Constants.DataIndices.IN_BLANK_PRD)
    var in_imp: int = data_from_yau_07.decode_u16(Constants.DataIndices.IN_IMPULS_PRD)
    var out_blank: int = data_from_yau_07.decode_u16(Constants.DataIndices.OUT_BLANK_PRD)
    var out_imp: int = data_from_yau_07.decode_u16(Constants.DataIndices.OUT_IMPULS_PRD)
    process_sockets_vert(in_blank, in_imp, 16, 1)
    process_sockets_horizon(out_blank, out_imp, 16, 2)


func process_sockets_horizon(blank: int, imp: int, count: int, col: int):
    for i in count:
        var socket_status = node_select1.get_node2(col+i, shift).get_child(1, false)
        var frame_type = Constants.Frame.WORK

        if (blank & (1 << i)) != 0:
            frame_type = Constants.Frame.CONSTANT
        elif (imp & (1 << i)) != 0:
            frame_type = Constants.Frame.VARIABLE

        set_frame(socket_status, frame_type)
        if i == 0:   # СИ_2_в_УФ
            set_frame(CI_1_UF, frame_type)
        elif i == 1: # СИ_2_в_УФ
            set_frame(CI_2_UF, frame_type)
        if i == 2:   # СИ_3_в_УФ
            set_frame(CI_3_UF, frame_type)
        if i == 4:   # Модуляция_УМ_2
            pass
        if i == 5:   # Модуляция_УМ_3
            pass
        if i == 9:   # ФГОЗ_3
            pass


func process_sockets_vert(blank: int, imp: int, count: int, col: int):
    for i in count:
        var socket_status = node_select1.get_node2(col, i + shift+1).get_child(1, false)
        var frame_type = Constants.Frame.WORK

        if (blank & (1 << i)) != 0:
            frame_type = Constants.Frame.CONSTANT
        elif (imp & (1 << i)) != 0:
            frame_type = Constants.Frame.VARIABLE

        set_frame(socket_status, frame_type)

        if Constants.CURRENT_MODE == Constants.MODE.PRD_H:
            if i == 1:  # СЗИ_2_от_УФ
                set_frame(CZI_2_FS, frame_type)
            if i == 2:  # СЗИ_3_от_УФ
                set_frame(CZI_3_FS, frame_type)
        elif Constants.CURRENT_MODE == Constants.MODE.PRD_B:
            if i == 3:  # СЗИ_4_от_УФ
                set_frame(CZI_4_FS, frame_type)
            if i == 4:  # СЗИ_5_от_УФ
                set_frame(CZI_5_FS, frame_type)
        elif Constants.CURRENT_MODE == Constants.MODE.PRD_K:
            if i == 0:  # СЗИ_1_от_УФ
                set_frame(CZI_1_FS, frame_type)
            if i == 5:  # СЗИ_6_от_УФ
                set_frame(CZI_6_FS, frame_type)
            if i == 6:  # СЗИ_7_от_УФ
                set_frame(CZI_7_FS, frame_type)

        if Constants.CURRENT_MODE == Constants.MODE.PRD_H:
            if i == 9: # СИ_2_от_ФС
                set_frame(CI_2_FS, frame_type)
                if frame_type == Constants.Frame.CONSTANT and status_fs_1 != Constants.Frame.CONSTANT:
                    emit_signal('signal_FS_is_ready', Constants.META.CI_2_OT_FS)
                status_fs_1 = frame_type
            if i == 10: # СИ_3_от_ФС
                set_frame(CI_3_FS, frame_type)
                if frame_type == Constants.Frame.CONSTANT and status_fs_2 != Constants.Frame.CONSTANT:
                    emit_signal('signal_FS_is_ready', Constants.META.CI_3_OT_FS)
                status_fs_2 = frame_type
        elif Constants.CURRENT_MODE == Constants.MODE.PRD_B:
            if i == 11: # СИ_4_от_ФС
                set_frame(CI_4_FS, frame_type)
                if frame_type == Constants.Frame.CONSTANT and status_fs_1 != Constants.Frame.CONSTANT:
                    emit_signal('signal_FS_is_ready', Constants.META.CI_4_OT_FS)
                status_fs_1 = frame_type
            if i == 12: # СИ_5_от_ФС
                set_frame(CI_5_FS, frame_type)
                if frame_type == Constants.Frame.CONSTANT and status_fs_2 != Constants.Frame.CONSTANT:
                    emit_signal('signal_FS_is_ready', Constants.META.CI_5_OT_FS)
                status_fs_2 = frame_type
        elif Constants.CURRENT_MODE == Constants.MODE.PRD_K:
            if i == 8: # СИ_1_от_ФС
                set_frame(CI_1_FS, frame_type)
                if frame_type == Constants.Frame.CONSTANT and status_fs_1 != Constants.Frame.CONSTANT:
                    emit_signal('signal_FS_is_ready', Constants.META.CI_1_OT_FS)
                status_fs_1 = frame_type
            if i == 13: # СИ_6_от_ФС
                set_frame(CI_6_FS, frame_type)
                if frame_type == Constants.Frame.CONSTANT and status_fs_2 != Constants.Frame.CONSTANT:
                    emit_signal('signal_FS_is_ready', Constants.META.CI_6_OT_FS)
                status_fs_2 = frame_type
            if i == 14: # СИ_7_от_ФС
                set_frame(CI_7_FS, frame_type)
                if frame_type == Constants.Frame.CONSTANT and status_fs_3 != Constants.Frame.CONSTANT:
                    emit_signal('signal_FS_is_ready', Constants.META.CI_7_OT_FS)
                status_fs_3 = frame_type


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


## Создает связь между кнопками
func create_link_button(node, count_rows_sart: int, count_rows_end: int, coln_start: int, coln_end: int):
    ## META_EMS_G[[Номер входа, Номер выхода]]
    var META_EMS_G: Array = []
    for i_row in 16:
        var INPUT = 1
        var OUTPUT = 47
        for i_colum in 16:
            META_EMS_G.append([INPUT+i_row, OUTPUT+i_colum])
            button_link_meta[OUTPUT+i_colum] = 0

    var count_register = 0
    for i_row in range(count_rows_sart, count_rows_end):
        for i_col in range (coln_start, coln_end):
            var chk_node = node.get_node2(i_col, i_row)
            var mouse_area = chk_node.get_child(0, false)
            var chk_btn = chk_node.get_child(1, false)
            mouse_area.connect('mouse_entered', Callable(self, 'on_mouse_entered').bind(chk_btn))
            chk_btn.connect('mouse_entered', Callable(self, 'on_mouse_entered').bind(chk_btn))
            chk_btn.connect('toggled', Callable(self, '_on_btn_connect').bind(chk_btn))
            chk_btn.set_meta('device', META_EMS_G[count_register])
            count_register += 1


func on_mouse_entered(meta_area):
    var device = meta_area.get_meta('device')
    var y = device[0] + 1
    var x = device[1] - 45

    for i_y in 18:
        for i_x in 18:
            if i_y <= y and i_x <= x and i_y == y:
                var chest = $table1.get_node2(i_x, i_y+1).get_child(0, false)
                chest.color = Color(0.45, 0.36, 0.36, 0.5)
            elif i_y <= y and i_x <= x and i_x == x:
                var chest = $table1.get_node2(i_x, i_y+1).get_child(0, false)
                chest.color = Color(0.45, 0.36, 0.36, 0.5)
            else:
                var black = $table1.get_node2(i_x, i_y+1).get_child(0, false)
                black.color = Color(0, 0, 0, 0.0)


func on_mode_link(mode, list):
    ## Формирование команды для выбора устройства
    var meta = list.get_meta('device')
    var address_port_wr = Constants.BASE_PORTS.EMS_G+2
    Network.write_port_isa(address_port_wr, meta)  # Отправка команды

    ## Формирование команды для отправкы команды на устройство
    address_port_wr = Constants.BASE_PORTS.EMS_G+8
    var set_mode: int = 0x0000 if mode == 0 else 0x2000 if mode == 1 else 0x4000 if mode == 2 else 0x8000
    var node_prd: Node = get_parent().get_parent()
    for i_meta in 3:
        if meta == node_prd.current_meta[i_meta]:
            node_prd.modul_um[i_meta] = set_mode
            if node_prd.modul_um.has(0x8000):
                node_prd.timer_modul_um.wait_time = 2.3
                node_prd.timer_modul_um.start()
    Network.write_port_isa(address_port_wr, set_mode)


func _on_btn_connect(toggled_on: bool, chk_btn: Node):
    ## Формирование команды для выбора устройства
    var meta = chk_btn.get_meta('device')
    ## Формирование команды для отправкы команды на устройство
    if toggled_on:
        button_link_meta[meta[1]] += 1 << meta[0]-1
    else:
        button_link_meta[meta[1]] -= 1 << meta[0]-1

    Network.write_port_isa(Constants.BASE_PORTS.EMS_G+2, meta[1]) # Отправка команды
    Network.write_port_isa(Constants.BASE_PORTS.EMS_G+4, button_link_meta[meta[1]])
    Network.read_port_isa([Constants.BASE_PORTS.EMS_G+4])
