//
//  SDLHoleMessageDecoder.swift
//  punchnet
//
//  Created by 安礼成 on 2026/4/15.
//
import Foundation
import NIOCore
import NIOPosix
import SwiftProtobuf

// --MARK: 进来的消息, 这里需要采用代数类型来表示
enum SDLHoleMessage {
    case data(SDLData)
    case register(SDLRegister)
    case registerAck(SDLRegisterAck)
    case stunProbeReply(SDLStunProbeReply)
    case stunReply(SDLStunReply)
}

enum SDLHoleControlMessage {
    case register(SDLRegister)
    case registerAck(SDLRegisterAck)
    case stunProbeReply(SDLStunProbeReply)
    case stunReply(SDLStunReply)
}

enum SDLHoleInboundMessage {
    case control(SDLHoleControlMessage)
    case data(SDLData)
}

extension SDLHoleMessage {
    var inboundMessage: SDLHoleInboundMessage {
        switch self {
        case .data(let data):
            return .data(data)
        case .register(let register):
            return .control(.register(register))
        case .registerAck(let registerAck):
            return .control(.registerAck(registerAck))
        case .stunProbeReply(let stunProbeReply):
            return .control(.stunProbeReply(stunProbeReply))
        case .stunReply(let stunReply):
            return .control(.stunReply(stunReply))
        }
    }
}

extension SDLHoleMessage {
    
    static func decode(buffer: inout ByteBuffer) throws -> SDLHoleMessage? {
        guard let type = buffer.readInteger(as: UInt8.self),
              let packetType = SDLPacketType(rawValue: type) else {
            return nil
        }
        
        switch packetType {
        case .data:
            guard let bytes = buffer.readBytes(length: buffer.readableBytes),
                  let dataPacket = try? SDLData(serializedBytes: bytes) else {
                return nil
            }
            return .data(dataPacket)
        case .register:
            guard let bytes = buffer.readBytes(length: buffer.readableBytes),
               let registerPacket = try? SDLRegister(serializedBytes: bytes) else {
                return nil
            }
            return .register(registerPacket)
        case .registerAck:
            guard let bytes = buffer.readBytes(length: buffer.readableBytes),
               let registerAck = try? SDLRegisterAck(serializedBytes: bytes) else {
                return nil
            }
            return .registerAck(registerAck)
        case .stunProbeReply:
            guard let bytes = buffer.readBytes(length: buffer.readableBytes),
               let stunProbeReply = try? SDLStunProbeReply(serializedBytes: bytes) else {
                return nil
            }
            return .stunProbeReply(stunProbeReply)
        case .stunReply:
            guard let bytes = buffer.readBytes(length: buffer.readableBytes),
               let stunReply = try? SDLStunReply(serializedBytes: bytes) else {
                return nil
            }
            return .stunReply(stunReply)
        default:
            SDLLogger.log("[SDLUDPHole] decode miss type: \(type)", for: .debug)
            
            return nil
        }
    }
    
}
