﻿using System;

namespace think.RxMsg.Bus
{
    public interface IBus: IDisposable
    {
        /// <summary>
        /// Subscribes to a channel for messages of type <see cref="T"/>. Messages are wrapped in <see cref="MessageEntity{T}"/>
        /// </summary>
        /// <typeparam name="T">The message type to filter for</typeparam>
        /// <param name="channel">The channel to subscribe to</param>
        /// <param name="observer">The subscriber</param>
        /// <returns>The subscription</returns>
        IDisposable Subscribe<T>(string channel, IObserver<MessageEntity<T>> observer);

        /// <summary>
        /// Subscribe to the default channel for type <see cref="T"/>
        /// </summary>
        /// <typeparam name="T">The message type to filter for</typeparam>
        /// <param name="observer">The subscriber</param>
        /// <returns>The subscription</returns>
        IDisposable Subscribe<T>(IObserver<MessageEntity<T>> observer);

        /// <summary>
        /// Create an observable for the subscription to a channel
        /// </summary>
        /// <typeparam name="T">The message type to filter for</typeparam>
        /// <param name="channel">The channel to create the observable for</param>
        /// <returns>An observable stream that represents the channel</returns>
        IObservable<MessageEntity<T>> Observe<T>(string channel);

        /// <summary>
        /// Create an observable for the subscription to the default channel for type <see cref="T"/>
        /// </summary>
        /// <typeparam name="T">The message type to filter for</typeparam>
        /// <returns>An observable stream that represents the channel</returns>
        IObservable<MessageEntity<T>> Observe<T>();

        /// <summary>
        /// Publish a new message to a channel. Messages are wrapped in <see cref="MessageEntity{T}"/>
        /// </summary>
        /// <typeparam name="T">The type of the message to publish</typeparam>
        /// <param name="channel">The channel to post to</param>
        /// <param name="message">The actual message content</param>
        void Publish<T>(string channel, T message);

        /// <summary>
        /// Publish a new message to the default channel for type <see cref="T"/>. Messages are wrapped in <see cref="MessageEntity{T}"/>
        /// </summary>
        /// <typeparam name="T">The type of the message to publish</typeparam>
        /// <param name="channel">The channel to post to</param>
        /// <param name="message">The actual message content</param>
        void Publish<T>(T message);
    }
}