// Marshaling — shared "walk a native array of owned-struct entries, convert to Swift value
// types, free the native list" pattern. Identical shape for vc_device_list / vc_channel_list
// / vc_user_list / vc_stream_summary_list / vc_account_list (all core-allocated, caller-freed
// per voicecat.h). The matching vc_free_*_list call happens INSIDE each function here,
// immediately after the conversion, so callers never need to remember to free anything
// themselves. This is the Swift analog of the C# client's Marshaling.cs.

import VoiceCatC
import Foundation

/// Internal marshaling helpers — convert core-allocated C arrays to Swift arrays and
/// immediately free the native list. Not part of the public API.
internal enum Marshaling {
    /// Convert a nullable `const char*` to a Swift `String` (empty if NULL).
    @inline(__always)
    static func string(_ ptr: UnsafePointer<CChar>?) -> String {
        guard let ptr else { return "" }
        return String(cString: ptr)
    }

    static func devices(_ list: inout vc_device_list) -> [Device] {
        guard let items = list.items else { vc_free_device_list(&list); return [] }
        var result: [Device] = []
        result.reserveCapacity(list.count)
        for i in 0..<list.count {
            let d = items.advanced(by: i).pointee
            result.append(Device(id: string(d.id), name: string(d.name), isDefault: d.is_default != 0))
        }
        vc_free_device_list(&list)
        return result
    }

    static func channels(_ list: inout vc_channel_list) -> [Channel] {
        guard let items = list.items else { vc_free_channel_list(&list); return [] }
        var result: [Channel] = []
        result.reserveCapacity(list.count)
        for i in 0..<list.count {
            let c = items.advanced(by: i).pointee
            result.append(Channel(id: c.id, parentId: c.parent_id, name: string(c.name),
                                  topic: string(c.topic), passwordProtected: c.password_protected != 0,
                                  maxUsers: c.max_users))
        }
        vc_free_channel_list(&list)
        return result
    }

    static func users(_ list: inout vc_user_list) -> [User] {
        guard let items = list.items else { vc_free_user_list(&list); return [] }
        var result: [User] = []
        result.reserveCapacity(list.count)
        for i in 0..<list.count {
            let u = items.advanced(by: i).pointee
            result.append(User(id: u.id, nickname: string(u.nickname), isGuest: u.is_guest != 0,
                               channelId: u.channel_id, selfMicMuted: u.self_mic_muted != 0,
                               selfDeafened: u.self_deafened != 0, serverMuted: u.server_muted != 0,
                               serverDeafened: u.server_deafened != 0))
        }
        vc_free_user_list(&list)
        return result
    }

    static func streamSummaries(_ list: inout vc_stream_summary_list) -> [StreamSummary] {
        guard let items = list.items else { vc_free_stream_summary_list(&list); return [] }
        var result: [StreamSummary] = []
        result.reserveCapacity(list.count)
        for i in 0..<list.count {
            let s = items.advanced(by: i).pointee
            result.append(StreamSummary(streamId: s.stream_id, kind: VoiceCatStreamKind(s.kind),
                                        label: string(s.label)))
        }
        vc_free_stream_summary_list(&list)
        return result
    }

    static func accounts(_ list: inout vc_account_list) -> [Account] {
        guard let items = list.items else { vc_free_account_list(&list); return [] }
        var result: [Account] = []
        result.reserveCapacity(list.count)
        for i in 0..<list.count {
            let a = items.advanced(by: i).pointee
            result.append(Account(username: string(a.username), isAdmin: a.is_admin != 0,
                                  createdAtUnixMs: a.created_at_unix_ms,
                                  lastLoginUnixMs: a.last_login_unix_ms))
        }
        vc_free_account_list(&list)
        return result
    }

    static func remoteStreamState(_ s: vc_remote_stream_state) -> RemoteStreamState {
        RemoteStreamState(gain: s.gain, muted: s.muted != 0, noiseReduction: s.noise_reduction != 0)
    }

    static func audioConfig(_ c: vc_audio_config) -> AudioConfig {
        AudioConfig(codec: c.codec, stereo: c.mode != 0, sampleRate: c.sample_rate,
                    bitrateBps: c.bitrate_bps, frameMs: c.frame_ms, application: c.application,
                    fec: c.fec != 0, expectedPacketLoss: c.expected_packet_loss,
                    dtx: c.dtx != 0, complexity: c.complexity, dred: c.dred != 0)
    }

    static func permissions(_ p: vc_permissions) -> Permissions {
        Permissions(canCreateTempChannel: p.can_create_temp_channel != 0,
                    canKick: p.can_kick != 0, canBan: p.can_ban != 0,
                    canMoveUsers: p.can_move_users != 0,
                    canAdminAccounts: p.can_admin_accounts != 0,
                    isAdmin: p.is_admin != 0)
    }
}
