//
//  SDLNoticeClient.swift
//  Tun
//
//  Created by 安礼成 on 2024/5/20.
//

import Foundation

//
//  SDLanServer.swift
//  Tun
//
//  Created by 安礼成 on 2024/1/31.
//

import Foundation
import NIOCore
import NIOPosix

// 处理和sn-server服务器之间的通讯
final class SDLNoticeClient {
    private let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
    let (writeStream, writeContinuation) = AsyncStream<Data>.makeStream(of: Data.self)
    private var task: Task<Void, Never>?
    
    private var channel: Channel
    private let noticePort: Int
    
    // 启动函数
    init(noticePort: Int) throws {
        self.noticePort = noticePort
        
        let bootstrap = DatagramBootstrap(group: self.group)
            .channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)
            .channelInitializer { channel in
                channel.pipeline.addHandler(SDLNoticeClientInboundHandler())
            }
        
        self.channel = try bootstrap.bind(host: "0.0.0.0", port: 0).wait()
        SDLLogger.shared.log("[SDLNoticeClient] started", level: .debug)
    }
    
    func start() {
        let channel = self.channel
        self.task = Task.detached {
            guard let remoteAddress = try? await SDLAddressResolver.shared.resolve(host: "127.0.0.1", port: self.noticePort) else {
                return
            }
            
            for await data in self.writeStream {
                if Task.isCancelled {
                    break
                }

                let buf = channel.allocator.buffer(bytes: data)
                let envelope = AddressedEnvelope<ByteBuffer>(remoteAddress: remoteAddress, data: buf)
                channel.eventLoop.execute {
                    channel.writeAndFlush(envelope, promise: nil)
                }
            }
        }
        
    }
    
    // 处理写入逻辑
    func send(data: Data) {
        self.writeContinuation.yield(data)
    }
    
    func waitClose() async throws {
        try await self.channel.closeFuture.get()
    }
    
    deinit {
        self.writeContinuation.finish()
        self.task?.cancel()
        try? self.group.syncShutdownGracefully()
    }
    
}

extension SDLNoticeClient {
    
    private class SDLNoticeClientInboundHandler: ChannelInboundHandler {
        typealias InboundIn = AddressedEnvelope<ByteBuffer>
    }
    
}
