using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Timeline.Entities;
using Timeline.Models;
namespace Timeline.Services
{
    [Serializable]
    public class TimelineMemberOperationException : Exception
    {
        public TimelineMemberOperationException() : base(Resources.Services.Exception.TimelineMemberOperationException) { }
        public TimelineMemberOperationException(string message) : base(message) { }
        public TimelineMemberOperationException(string message, Exception inner) : base(message, inner) { }
        protected TimelineMemberOperationException(
          System.Runtime.Serialization.SerializationInfo info,
          System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
        public TimelineMemberOperationException(int index, Exception inner) : base(MakeIndexMessage(index), inner) { Index = index; }
        private static string MakeIndexMessage(int index) => string.Format(CultureInfo.CurrentCulture,
            Resources.Services.Exception.TimelineMemberOperationExceptionIndex, index);
        public int? Index { get; set; }
    }
    /// 
    /// This define the common interface of both personal timeline
    /// and normal timeline.
    /// 
    /// 
    /// The "name" parameter in method means name of timeline in
    ///  while username of the owner
    /// of the personal timeline in .
    /// 
    public interface IBaseTimelineService
    {
        /// 
        /// Get all the posts in the timeline.
        /// 
        /// Username or the timeline name. See remarks of .
        /// A list of all posts.
        /// Thrown when  is null.
        /// 
        /// Thrown when timeline name is of bad format.
        /// For normal timeline, it means name is an empty string.
        /// For personal timeline, it means the username is of bad format,
        /// the inner exception should be a .
        /// 
        /// 
        /// Thrown when timeline does not exist.
        /// For normal timeline, it means the name does not exist.
        /// For personal timeline, it means the user of that username does not exist
        /// and the inner exception should be a .
        /// 
        Task> GetPosts(string name);
        /// 
        /// Create a new post in timeline.
        /// 
        /// Username or the timeline name. See remarks of .
        /// The author's username.
        /// The content.
        /// The time of the post. If null, then use current time.
        /// 
        /// Thrown when  or  or  is null.
        /// 
        /// Thrown when timeline name is of bad format.
        /// For normal timeline, it means name is an empty string.
        /// For personal timeline, it means the username is of bad format,
        /// the inner exception should be a .
        /// 
        /// 
        /// Thrown when timeline does not exist.
        /// For normal timeline, it means the name does not exist.
        /// For personal timeline, it means the user of that username does not exist
        /// and the inner exception should be a .
        /// 
        /// Thrown if  is of bad format.
        /// Thrown if  does not exist.
        Task Post(string name, string author, string content, DateTime? time);
        /// 
        /// Set the visibility permission of a timeline. 
        /// 
        /// Username or the timeline name. See remarks of .
        /// The new visibility.
        /// Thrown when  is null.
        /// 
        /// Thrown when timeline name is of bad format.
        /// For normal timeline, it means name is an empty string.
        /// For personal timeline, it means the username is of bad format,
        /// the inner exception should be a .
        /// 
        /// 
        /// Thrown when timeline does not exist.
        /// For normal timeline, it means the name does not exist.
        /// For personal timeline, it means the user of that username does not exist
        /// and the inner exception should be a .
        /// 
        Task SetVisibility(string name, TimelineVisibility visibility);
        /// 
        /// Set the description of a timeline.
        /// 
        /// Username or the timeline name. See remarks of .
        /// The new description.
        /// Thrown when  or  is null.
        /// 
        /// Thrown when timeline name is of bad format.
        /// For normal timeline, it means name is an empty string.
        /// For personal timeline, it means the username is of bad format,
        /// the inner exception should be a .
        /// 
        /// 
        /// Thrown when timeline does not exist.
        /// For normal timeline, it means the name does not exist.
        /// For personal timeline, it means the user of that username does not exist
        /// and the inner exception should be a .
        /// 
        Task SetDescription(string name, string description);
        /// 
        /// Add members to a timeline.
        /// 
        /// Username or the timeline name. See remarks of .
        /// A list of new members' usernames
        /// Thrown when  or  is null.
        /// 
        /// Thrown when timeline name is of bad format.
        /// For normal timeline, it means name is an empty string.
        /// For personal timeline, it means the username is of bad format,
        /// the inner exception should be a .
        /// 
        /// 
        /// Thrown when timeline does not exist.
        /// For normal timeline, it means the name does not exist.
        /// For personal timeline, it means the user of that username does not exist
        /// and the inner exception should be a .
        /// 
        /// 
        /// TODO! complete this documents.
        /// 
        Task AddMember(string name, IList usernames);
        /// 
        /// Remove members to a timeline.
        /// 
        /// Username or the timeline name. See remarks of .
        /// A list of members' usernames
        /// Thrown when  is null.
        /// 
        /// Thrown when timeline name is of bad format.
        /// For normal timeline, it means name is an empty string.
        /// For personal timeline, it means the username is of bad format,
        /// the inner exception should be a .
        /// 
        /// 
        /// Thrown when timeline does not exist.
        /// For normal timeline, it means the name does not exist.
        /// For personal timeline, it means the user of that username does not exist
        /// and the inner exception should be a .
        /// 
        Task RemoveMember(string name, IList usernames);
    }
    /// 
    /// Service for normal timeline.
    /// 
    public interface ITimelineService : IBaseTimelineService
    {
        /// 
        /// Get the timeline info.
        /// 
        /// The name of the timeline.
        /// The timeline info.
        Task GetTimeline(string name);
        /// 
        /// Create a timeline.
        /// 
        /// The name of the timeline.
        /// The owner of the timeline.
        Task CreateTimeline(string name, string owner);
    }
    public interface IPersonalTimelineService : IBaseTimelineService
    {
        /// 
        /// Get the timeline info.
        /// 
        /// The username of the owner of the personal timeline.
        /// The timeline info.
        Task GetTimeline(string username);
    }
}