import Foundation
import NIOCore

#if canImport(CryptoKit)
import CryptoKit
#else
import Crypto
#endif

struct ServerMessage {

    static let authTokenSize = SHA256.byteCount

    static let length = authTokenSize + Message.length

    let authToken: Data

    let message: Message

    init(authToken: Data, message: Message) {
        self.authToken = authToken
        self.message = message
    }
    
    /**
     Decode a message from a byte buffer.
     The buffer must contain at least `ServerMessage.length` bytes, or it will return `nil`.
     - Parameter buffer: The buffer containing the bytes.
     */
    init?(decodeFrom buffer: ByteBuffer) {
        guard let data = buffer.getBytes(at: 0, length: ServerMessage.length) else {
            return nil
        }
        self.authToken = Data(data.prefix(ServerMessage.authTokenSize))
        self.message = Message(decodeFrom: Data(data.dropFirst(ServerMessage.authTokenSize)))
    }

    var encoded: Data {
        authToken + message.encoded
    }

    static func token(from buffer: ByteBuffer) -> Data? {
        guard buffer.readableBytes == authTokenSize else {
            return nil
        }
        guard let bytes = buffer.getBytes(at: 0, length: authTokenSize) else {
            return nil
        }
        return Data(bytes)
    }
}
