using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using WkHtmlTo.Wrapper.Logging;

namespace WkHtmlTo.Wrapper
{
    /// <summary>
    /// The result of a pdf conversion with <c>wkhtmlto</c>
    /// </summary>
    public abstract class ConversionResult
    {
        private readonly List<ConversionOutputEvent> _events;
        private readonly Stopwatch _stopwatch;

        /// <summary>
        /// List of output events that occurred while converting to pdf
        /// </summary>
        public IEnumerable<ConversionOutputEvent> Events => _events;

        /// <summary>
        /// List of output logs that occurred while converting to pdf
        /// </summary>
        public IEnumerable<string> Logs => _events.Select(x => x.Message);

        /// <summary>
        /// Total eapsed milliseconds while processing conversion to pdf
        /// </summary>
        public long TotalElapsedMilliseconds => _stopwatch.ElapsedMilliseconds;

        /// <summary>
        /// Determines if conversion process outputed any errors based on output events
        /// </summary>
        public bool HasErrors => _events.Any(x => x.EventType == ConversionOutputEventType.Error);

        /// <summary>
        /// Total bytes generated from conversion
        /// </summary>
        public abstract long TotalBytes { get; }

        /// <summary>
        /// Determines whether conversion was successfully or not
        /// </summary>
        public abstract bool Success { get; }

        /// <summary>
        /// Get generated bytes from conversion
        /// </summary>
        /// <returns>Conversion in byte array</returns>
        public abstract byte[] GetBytes();

        /// <summary>
        /// Get stream from conversion
        /// </summary>
        /// <returns>Conversion stream</returns>
        public abstract Stream GetStream();

        internal virtual void SetResult(object result)
        {
            _stopwatch.Stop();
        }

        internal ConversionResult()
        {
            _stopwatch = Stopwatch.StartNew();
            _events = new List<ConversionOutputEvent>();
        }

        internal void AddEvent(ConversionOutputEvent ev)
            => _events.Add(ev);
    }
}
