use jam_types::ServiceId;
use jsonrpsee::{
	core::{RpcResult, SubscriptionResult},
	proc_macros::rpc,
	PendingSubscriptionSink,
};

mod server;
pub use self::server::*;

/// JSON-RPC interface.
///
/// Inteded for sending and receiving small amounts of mostly textual data.
#[rpc(client, server)]
pub trait Rpc {
	/// Returns logs of the specified service or `None` if such service isn't known to the builder.
	#[method(name = "logs")]
	async fn logs(&self, service_id: ServiceId) -> RpcResult<Option<Vec<LogMessage>>>;

	/// Subscribe to logs of the specified service.
	///
	/// Returns all existing logs and new logs as they're produced.
	#[subscription(name = "subscribeLogs", item = LogMessage)]
	async fn subscribe_logs(&self, service_id: ServiceId) -> SubscriptionResult;
}

/// Log message related to a service.
#[derive(Clone, serde::Serialize, serde::Deserialize)]
pub struct LogMessage {
	/// UNIX timestamp.
	pub timestamp: u64,
	/// Severity level.
	pub level: log::Level,
	/// Log target.
	pub target: String,
	/// Message text.
	pub message: String,
}

impl LogMessage {
	#[inline]
	pub(crate) fn size_in_bytes(&self) -> usize {
		std::mem::size_of::<Self>() + self.target.len() + self.message.len()
	}

	pub(crate) fn as_ref(&self) -> LogMessageRef<'_> {
		LogMessageRef {
			timestamp: self.timestamp,
			level: self.level,
			target: self.target.as_ref(),
			message: self.message.as_ref(),
		}
	}
}

#[derive(serde::Serialize)]
pub(crate) struct LogMessageRef<'a> {
	pub timestamp: u64,
	pub level: log::Level,
	pub target: &'a str,
	pub message: &'a str,
}
