using C4IT.F4SD.SupportCaseProtocoll.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using static C4IT.Logging.cLogManager;

namespace FasdDesktopUi.Basics.Services.ProtocollService
{
    internal class F4SDProtocoll
    {
        private readonly ICollection<ProtocollEntryBase> _protocollEntries = new List<ProtocollEntryBase>();

        public static F4SDProtocoll Instance { get; private set; } = new F4SDProtocoll();

        private F4SDProtocoll() { }

        internal void Add(ProtocollEntryBase entry) => _protocollEntries.Add(entry);
        internal void Add(IEnumerable<ProtocollEntryBase> entries)
        {
            foreach (var entry in entries)
            {
                Add(entry);
            }
        }

        internal void Clear() => _protocollEntries.Clear();

        internal T GetLatestOfType<T>() where T : ProtocollEntryBase => _protocollEntries.OfType<T>().LastOrDefault();

        internal IEnumerable<T> GetOfType<T>(int? count = null) where T : ProtocollEntryBase
        {
            if(count.HasValue)
                return _protocollEntries.OfType<T>().Reverse().Take(count.Value).Reverse();
            return _protocollEntries.OfType<T>();
        }

        internal IEnumerable<ProtocollEntryBase> GetAll() => _protocollEntries;

        internal DataObject GetLatestOfTypeAsDataObject<T>(bool skipHtmlFrame) where T : ProtocollEntryBase
        {
            ProtocollEntryBase entry = _protocollEntries.OfType<T>().LastOrDefault();

            if (entry is null)
                return new DataObject();

            return GetDataObjectOf(new ProtocollEntryBase[] { entry }, skipHtmlFrame);
        }

        internal DataObject GetOfTypeAsDataObject<T>(bool skipHtmlFrame, int? count = null) where T : ProtocollEntryBase
            => GetDataObjectOf(GetOfType<T>(count).Cast<ProtocollEntryBase>(), skipHtmlFrame);

        internal DataObject GetAllAsDataObject(bool skipHtmlFrame)
            => GetDataObjectOf(_protocollEntries, skipHtmlFrame);

        private DataObject GetDataObjectOf(IEnumerable<ProtocollEntryBase> entries, bool skipHtmlFrame, int? count = null)
        {
            DataObject dataObject = new DataObject();

            const string asciiSeparator = "\n\n\n";
            const string htmlSeparator = "<br/><hr/><br/>";

            try
            {
                string ascii = string.Empty;
                string html = string.Empty;

                if (count.HasValue)
                    entries = entries.Reverse().Take(count.Value).Reverse();

                foreach (ProtocollEntryBase entry in entries)
                {
                    string entryAscii = entry.AsciiContent;
                    if (!string.IsNullOrEmpty(entryAscii))
                    {
                        ascii += entryAscii;
                        ascii += asciiSeparator;
                    }

                    string entryHtml = entry.HtmlContent;
                    if (!string.IsNullOrEmpty(entryHtml))
                    {
                        html += entryHtml;
                        html += htmlSeparator;
                    }
                }

                if (ascii.EndsWith(asciiSeparator))
                    ascii = ascii.Remove(ascii.Length - asciiSeparator.Length);

                if (html.EndsWith(htmlSeparator))
                    html = html.Remove(html.Length - htmlSeparator.Length);

                dataObject.SetText(ascii);

                if (!string.IsNullOrEmpty(html))
                {
                    html = skipHtmlFrame ? html : cUtility.GetHtmlFrame(html);
                    dataObject.SetText(html, TextDataFormat.Html);
                }
            }
            catch (Exception ex)
            {
                LogException(ex);
            }

            return dataObject;
        }
    }
}
