//
//  NatsStreamDelegate.swift
//  SwiftNatsNueve
//
//  Created by Denis Kozhukhov on 11/03/2020.
//  Copyright © 2020 Denis Kozhukhov. All rights reserved.
//

public protocol NatsDelegate: class {
	func natsDidConnect(nats: Nats)
	func natsDidDisconnect(nats: Nats, error: NSError?)
	func natsDidReceiveMessage(nats: Nats, msg: NatsMessage)
	func natsDidReceivePing(nats: Nats)
}

public struct NatsSubscription {
	public let id: String
	public let subject: String
	public let queueGroup: String
	fileprivate(set) var count: UInt

	func sub() -> String {
		let group: () -> String = {
			if queueGroup.count > 0 {
				return "\(queueGroup) "
			}
			return queueGroup
		}

		return "\(Proto.SUB.rawValue) \(subject) \(group())\(id)\r\n"
	}

	func unsub(_ max: UInt32) -> String {
		let wait: () -> String = {
			if max > 0 {
				return " \(max)"
			}
			return ""
		}
        return "\(Proto.UNSUB.rawValue) \(id)\(String(describing: wait))\r\n"
	}

	mutating func counter() {
		count += 1
	}
}

public struct NatsMessage {
	public let subject: String
	public let count: UInt
	public var reply: String?
	public var payload: String?
    public let data: Data?
}

internal enum Proto: String {
	case CONNECT = "CONNECT"
	case SUB = "SUB"
	case UNSUB = "UNSUB"
	case PUB = "PUB"
	case MSG = "MSG"
	case INFO = "INFO"
	case OK = "+OK"
	case ERR = "-ERR"
	case PONG = "PONG"
	case PING = "PING"
}

internal struct Server {
	let serverId: String
	let version: String
	let go: String
	let host: String
	let port: UInt
	let authRequired: Bool
	let sslRequired: Bool
	let maxPayload: UInt

	init(data: [String: AnyObject]) {
		self.serverId = data["server_id"] as! String
		self.version = data["version"] as! String
		self.go = data["go"] as! String
		self.host = data["host"] as! String
		self.port = data["port"] as! UInt
		self.authRequired = data["auth_required"] as? Bool ?? false
		self.sslRequired = data["tls_required"] as? Bool ?? false
		self.maxPayload = data["max_payload"] as! UInt
	}
}
