extends Node


const PROTOCOL_TYPES: = {'yau07tx': yau07.YaU07, 'jsontx': capsrpb.CapsRpb}


class Socket extends PacketPeerUDP:
    func send_to(addr, data):
        self.set_dest_address(addr[0], addr[1])
        self.put_packet(data)


var poll_sockets: Array[Socket]
var units: Dictionary
var sock_unicast: Socket
var sock_capsrpb: Socket
var logger_page: Node


func create_socket(nm) -> Socket:
    var addr  = repsettings.UnitProfiles[nm][1]
    var port  = repsettings.UnitProfiles[nm][2]
    var broad = repsettings.UnitProfiles[nm][3]
    var bind  = repsettings.UnitProfiles[nm][4]
    var sock: = Socket.new()
    sock.set_broadcast_enabled(broad)
    var rc = Error.OK if not bind else sock.bind(port, addr)
    var errlevel = log.INFO if rc == Error.OK else log.ERROR
    log.message(errlevel, '%s: сокет:%s:%d привязанный:%s %s' % [nm, addr, port, ['нет', 'да'][int(bind)], error_string(rc)])
    return sock


func _ready() -> void:
    log.info('Модуль работы с сетью готов')
    poll_sockets.append(create_socket('уарэп-яу07-частный'))
    poll_sockets.append(create_socket('уарэп-яу07-общий'))
    poll_sockets.append(create_socket('уарэп-капсрпб-пол'))

    sock_unicast = poll_sockets[0]
    sock_capsrpb = poll_sockets[2]

    for unit_name in repsettings.UnitProfiles:
        var setting = repsettings.UnitProfiles[unit_name]
        var proto = setting[0]
        if proto in PROTOCOL_TYPES:
            var unit = PROTOCOL_TYPES[proto].new(unit_name)
            var unit_key = repsettings.get_unit_key(unit_name)
            units[unit_key] = unit
            if logger_page:
                unit.connect('line_changed', Callable(logger_page, 'on_line_changed').bind(unit_key))
                unit.connect('command_fail', Callable(logger_page, 'on_command_fail').bind(unit_key))

    for key in units: log.info('%s %s:%d' % [units[key].name, key[0], key[1]])


func poll_receive(sock: Socket, tick: int) -> bool:
    while sock.get_available_packet_count() > 0:
        var data: = sock.get_packet()
        var addr: = sock.get_packet_ip()
        var port: = sock.get_packet_port()
        var addr_port: = [addr, port]
        if addr_port in units: units[addr_port].parse(data, tick)
    return false


func _process(_delta: float) -> void:
    var tick = Time.get_ticks_msec()
    for addr in units:
        var unit = units[addr]
        match unit.process(tick):
            Error.OK: sock_unicast.send_to(addr, unit.tx_data)
            Error.FAILED: emit_signal('socket_error', 'ошибка: %s %s:%d' % [unit, addr[0], addr[1]])
    poll_sockets.any(func(sock): poll_receive(sock, tick))
