using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using API.DTOs.Update;
using API.Entities;
using API.Extensions;
namespace API.SignalR
{
    public static class MessageFactoryEntityTypes
    {
        public const string Series = "series";
        public const string Volume = "volume";
        public const string Chapter = "chapter";
        public const string CollectionTag = "collection";
        public const string ReadingList = "readingList";
    }
    public static class MessageFactory
    {
        /// 
        /// An update is available for the Kavita instance
        /// 
        public const string UpdateAvailable = "UpdateAvailable";
        /// 
        /// Used to tell when a scan series completes. This also informs UI to update series metadata
        /// 
        public const string ScanSeries = "ScanSeries";
        /// 
        /// Event sent out during Refresh Metadata for progress tracking
        /// 
        private const string CoverUpdateProgress = "CoverUpdateProgress";
        /// 
        /// Series is added to server
        /// 
        public const string SeriesAdded = "SeriesAdded";
        /// 
        /// Series is removed from server
        /// 
        public const string SeriesRemoved = "SeriesRemoved";
        /// 
        /// When a user is connects/disconnects from server
        /// 
        public const string OnlineUsers = "OnlineUsers";
        /// 
        /// When a series is added to a collection
        /// 
        public const string SeriesAddedToCollection = "SeriesAddedToCollection";
        /// 
        /// Event sent out during backing up the database
        /// 
        private const string BackupDatabaseProgress = "BackupDatabaseProgress";
        /// 
        /// Event sent out during cleaning up temp and cache folders
        /// 
        private const string CleanupProgress = "CleanupProgress";
        /// 
        /// Event sent out during downloading of files
        /// 
        private const string DownloadProgress = "DownloadProgress";
        /// 
        /// A cover was updated
        /// 
        public const string CoverUpdate = "CoverUpdate";
        /// 
        /// A custom site theme was removed or added
        /// 
        private const string SiteThemeProgress = "SiteThemeProgress";
        /// 
        /// A custom book theme was removed or added
        /// 
        private const string BookThemeProgress = "BookThemeProgress";
        /// 
        /// A type of event that has progress (determinate or indeterminate).
        /// The underlying event will have a name to give details on how to handle.
        /// 
        /// This is not an Event Name, it is used as the method only
        public const string NotificationProgress = "NotificationProgress";
        /// 
        /// Event sent out when Scan Loop is parsing a file
        /// 
        private const string FileScanProgress = "FileScanProgress";
        /// 
        /// A generic error that can occur in background processing
        /// 
        public const string Error = "Error";
        /// 
        /// When DB updates are occuring during a library/series scan
        /// 
        private const string ScanProgress = "ScanProgress";
        /// 
        /// When a library is created/deleted in the Server
        /// 
        public const string LibraryModified = "LibraryModified";
        /// 
        /// A user's progress was modified
        /// 
        public const string UserProgressUpdate = "UserProgressUpdate";
        /// 
        /// A user's account or preferences were updated and UI needs to refresh to stay in sync
        /// 
        public const string UserUpdate = "UserUpdate";
        /// 
        /// When bulk bookmarks are being converted
        /// 
        private const string ConvertBookmarksProgress = "ConvertBookmarksProgress";
        /// 
        /// When files are being scanned to calculate word count
        /// 
        private const string WordCountAnalyzerProgress = "WordCountAnalyzerProgress";
        /// 
        /// A generic message that can occur in background processing to inform user, but no direct action is needed
        /// 
        public const string Info = "Info";
        public static SignalRMessage ScanSeriesEvent(int libraryId, int seriesId, string seriesName)
        {
            return new SignalRMessage()
            {
                Name = ScanSeries,
                EventType = ProgressEventType.Single,
                Body = new
                {
                    LibraryId = libraryId,
                    SeriesId = seriesId,
                    SeriesName = seriesName
                }
            };
        }
        public static SignalRMessage SeriesAddedEvent(int seriesId, string seriesName, int libraryId)
        {
            return new SignalRMessage()
            {
                Name = SeriesAdded,
                Body = new
                {
                    SeriesId = seriesId,
                    SeriesName = seriesName,
                    LibraryId = libraryId
                }
            };
        }
        public static SignalRMessage SeriesRemovedEvent(int seriesId, string seriesName, int libraryId)
        {
            return new SignalRMessage()
            {
                Name = SeriesRemoved,
                Body = new
                {
                    SeriesId = seriesId,
                    SeriesName = seriesName,
                    LibraryId = libraryId
                }
            };
        }
        public static SignalRMessage WordCountAnalyzerProgressEvent(int libraryId, float progress, string eventType, string subtitle = "")
        {
            return new SignalRMessage()
            {
                Name = WordCountAnalyzerProgress,
                Title = "Analyzing Word count",
                SubTitle = subtitle,
                EventType = eventType,
                Progress = ProgressType.Determinate,
                Body = new
                {
                    LibraryId = libraryId,
                    Progress = progress,
                    EventTime = DateTime.Now
                }
            };
        }
        public static SignalRMessage CoverUpdateProgressEvent(int libraryId, float progress, string eventType, string subtitle = "")
        {
            return new SignalRMessage()
            {
                Name = CoverUpdateProgress,
                Title = "Refreshing Covers",
                SubTitle = subtitle,
                EventType = eventType,
                Progress = ProgressType.Determinate,
                Body = new
                {
                    LibraryId = libraryId,
                    Progress = progress,
                    EventTime = DateTime.Now
                }
            };
        }
        public static SignalRMessage BackupDatabaseProgressEvent(float progress, string subtitle = "")
        {
            return new SignalRMessage()
            {
                Name = BackupDatabaseProgress,
                Title = "Backing up Database",
                SubTitle = subtitle,
                EventType = progress switch
                {
                    0f => "started",
                    1f => "ended",
                    _ => "updated"
                },
                Progress = ProgressType.Determinate,
                Body = new
                {
                    Progress = progress
                }
            };
        }
        public static SignalRMessage CleanupProgressEvent(float progress, string subtitle = "")
        {
            return new SignalRMessage()
            {
                Name = CleanupProgress,
                Title = "Performing Cleanup",
                SubTitle = subtitle,
                EventType = progress switch
                {
                    0f => "started",
                    1f => "ended",
                    _ => "updated"
                },
                Progress = ProgressType.Determinate,
                Body = new
                {
                    Progress = progress
                }
            };
        }
        public static SignalRMessage UpdateVersionEvent(UpdateNotificationDto update)
        {
            return new SignalRMessage
            {
                Name = UpdateAvailable,
                Title = "Update Available",
                SubTitle = update.UpdateTitle,
                EventType = ProgressEventType.Single,
                Progress = ProgressType.None,
                Body = update
            };
        }
        public static SignalRMessage SeriesAddedToCollectionEvent(int tagId, int seriesId)
        {
            return new SignalRMessage
            {
                Name = SeriesAddedToCollection,
                Progress = ProgressType.None,
                EventType = ProgressEventType.Single,
                Body = new
                {
                    TagId = tagId,
                    SeriesId = seriesId
                }
            };
        }
        public static SignalRMessage ErrorEvent(string title, string subtitle)
        {
            return new SignalRMessage
            {
                Name = Error,
                Title = title,
                SubTitle = subtitle,
                Progress = ProgressType.None,
                EventType = ProgressEventType.Single,
                Body = new
                {
                    Title = title,
                    SubTitle = subtitle,
                }
            };
        }
        public static SignalRMessage InfoEvent(string title, string subtitle)
        {
            return new SignalRMessage
            {
                Name = Info,
                Title = title,
                SubTitle = subtitle,
                Progress = ProgressType.None,
                EventType = ProgressEventType.Single,
                Body = new
                {
                    Title = title,
                    SubTitle = subtitle,
                }
            };
        }
        public static SignalRMessage LibraryModifiedEvent(int libraryId, string action)
        {
            return new SignalRMessage
            {
                Name = LibraryModified,
                Title = "Library modified",
                Progress = ProgressType.None,
                EventType = ProgressEventType.Single,
                Body = new
                {
                    LibrayId = libraryId,
                    Action = action,
                }
            };
        }
        public static SignalRMessage DownloadProgressEvent(string username, string downloadName, float progress, string eventType = "updated")
        {
            return new SignalRMessage()
            {
                Name = DownloadProgress,
                Title = $"Downloading {downloadName}",
                SubTitle = $"Preparing {username.SentenceCase()} the download of {downloadName}",
                EventType = eventType,
                Progress = ProgressType.Determinate,
                Body = new
                {
                    UserName = username,
                    DownloadName = downloadName,
                    Progress = progress
                }
            };
        }
        /// 
        /// Represents a file being scanned by Kavita for processing and grouping
        /// 
        /// Does not have a progress as it's unknown how many files there are. Instead sends -1 to represent indeterminate
        /// 
        /// 
        /// 
        /// 
        public static SignalRMessage FileScanProgressEvent(string filename, string libraryName, string eventType)
        {
            return new SignalRMessage()
            {
                Name = FileScanProgress,
                Title = $"Scanning {libraryName}",
                SubTitle = Path.GetFileName(filename),
                EventType = eventType,
                Progress = ProgressType.Indeterminate,
                Body = new
                {
                    Title = $"Scanning {libraryName}",
                    Subtitle = filename,
                    Filename = filename,
                    EventTime = DateTime.Now,
                }
            };
        }
        public static SignalRMessage LibraryScanProgressEvent(string libraryName, string eventType, string seriesName = "")
        {
            return new SignalRMessage()
            {
                Name = ScanProgress,
                Title = $"Scanning {libraryName}",
                SubTitle = seriesName,
                EventType = eventType,
                Progress = ProgressType.Indeterminate,
                Body = null
            };
        }
        public static SignalRMessage CoverUpdateEvent(int id, string entityType)
        {
            return new SignalRMessage()
            {
                Name = CoverUpdate,
                Title = "Updating Cover",
                Progress = ProgressType.None,
                Body = new
                {
                    Id = id,
                    EntityType = entityType,
                }
            };
        }
        public static SignalRMessage UserProgressUpdateEvent(int userId, string username, int seriesId, int volumeId, int chapterId, int pagesRead)
        {
            return new SignalRMessage()
            {
                Name = UserProgressUpdate,
                Title = "Updating User Progress",
                Progress = ProgressType.None,
                Body = new
                {
                    UserId = userId,
                    Username = username,
                    SeriesId = seriesId,
                    VolumeId = volumeId,
                    ChapterId = chapterId,
                    PagesRead = pagesRead,
                }
            };
        }
        public static SignalRMessage SiteThemeProgressEvent(string subtitle, string themeName, string eventType)
        {
            return new SignalRMessage()
            {
                Name = SiteThemeProgress,
                Title = "Scanning Site Theme",
                SubTitle = subtitle,
                EventType = eventType,
                Progress = ProgressType.Indeterminate,
                Body = new
                {
                    ThemeName = themeName,
                }
            };
        }
        public static SignalRMessage BookThemeProgressEvent(string subtitle, string themeName, string eventType)
        {
            return new SignalRMessage()
            {
                Name = BookThemeProgress,
                Title = "Scanning Book Theme",
                SubTitle = subtitle,
                EventType = eventType,
                Progress = ProgressType.Indeterminate,
                Body = new
                {
                    ThemeName = themeName,
                }
            };
        }
        public static SignalRMessage UserUpdateEvent(int userId, string userName)
        {
            return new SignalRMessage()
            {
                Name = UserUpdate,
                Title = "User Update",
                Progress = ProgressType.None,
                Body = new
                {
                    UserId = userId,
                    UserName = userName
                }
            };
        }
        public static SignalRMessage ConvertBookmarksProgressEvent(float progress, string eventType)
        {
            return new SignalRMessage()
            {
                Name = ConvertBookmarksProgress,
                Title = "Converting Bookmarks to WebP",
                SubTitle = string.Empty,
                EventType = eventType,
                Progress = ProgressType.Determinate,
                Body = new
                {
                    Progress = progress,
                    EventTime = DateTime.Now
                }
            };
        }
    }
}