using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Semver;

namespace Katteker
{
    /// <inheritdoc />
    /// <summary>
    /// This class represents the release file which will published.
    /// </summary>
    public class Releases : IEnumerable<ReleaseEntry>
    {
        private readonly string _filePath;

        private SortedDictionary<SemVersion, ReleaseEntry> ReleaseEntries { get; }

        private Releases()
        {
            ReleaseEntries = new SortedDictionary<SemVersion, ReleaseEntry>();
        }

        /// <summary>
        /// Constructor with the path as paramter.
        /// </summary>
        public Releases(string path) : this()
        {
            _filePath = Path.Combine(path, Constants.Release);
            if (!File.Exists(_filePath)) return;
            AddRange(File.ReadAllLines(_filePath));
        }

        /// <summary>
        /// Constructor with the enumerable content.
        /// </summary>
        public Releases(IEnumerable<string> content) : this()
        {
            AddRange(content);
        }

        private void AddRange(IEnumerable<string> content)
        {
            foreach (var line in content)
            {
                var entry = new ReleaseEntry(line);
                ReleaseEntries.Add(entry.Version, entry);
            }
        }

        /// <summary>
        /// Write release file to disk.
        /// </summary>
        public void WriteReleaseFile()
        {
            File.WriteAllLines(_filePath, ReleaseEntries.Values.Select(x => x.EntryAsString));
        }

        /// <summary>
        /// Adds new entry to file.
        /// </summary>
        /// <param name="setupFilePath">Path to setup-file</param>
        /// <param name="version">Version of setup-file</param>
        /// <returns>Returns true if newest version.</returns>
        public ReleaseEntry Add(string setupFilePath, SemVersion version)
        {
            var sha1 = Utility.ComputeFileHash(setupFilePath);
            var setupFile = new FileInfo(setupFilePath);
            var entry = new ReleaseEntry(setupFile.Name, version, setupFile.Length, false, sha1);

            if (ReleaseEntries.ContainsValue(entry)) return entry;
            ReleaseEntries[version] = entry;
            return entry;
        }

        /// <summary>
        /// Is true if the entry is the last entry.
        /// </summary>
        /// <param name="entry"></param>
        /// <returns></returns>
        public bool IsLatestEntry(ReleaseEntry entry) => entry.Equals(ReleaseEntries.LastOrDefault().Value);

        /// <inheritdoc />
        public IEnumerator<ReleaseEntry> GetEnumerator() => ReleaseEntries.Values.GetEnumerator();

        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    }
}