using System;
using System.Collections.Generic;
using System.Linq;
using isnd.Data.Packages;
using Newtonsoft.Json;
using NuGet.Versioning;

namespace isnd.Data.Catalog
{
    public class RegistrationPage : HappyIdOwner
    {
        [JsonProperty("@id")]
        public string Id { get => GetId(); }
        private readonly string pkgid;
        private readonly List<PackageVersion> items;

        protected string Bid { get ; private set; }
        protected string ExternalUrl { get; }

        public RegistrationPage (string bid, string pkgid, string extUrl) : base(bid + "/" + pkgid + "/index.json")
        {
            Bid = bid;
            Parent = Bid + $"/{pkgid}/index.json";
            ExternalUrl = extUrl;
            this.items = new List<PackageVersion>();
            this.pkgid = pkgid;
        }

        public RegistrationPage(string bid, string pkgid, string extUrl, List<PackageVersion> versions) : this(bid, pkgid, extUrl)
        {
             AddVersionRange(versions);
        }

        public string GetPackageId()
        {
            return pkgid;
        }

        /// <summary>
        /// The array of registration leaves and their associate metadata
        /// </summary>
        /// <value></value>
        [JsonProperty("items")]

        public CatalogEntry[] Items { get => items.Select((p) => p.ToLeave(Bid, ExternalUrl)).ToArray(); }

        public void AddVersionRange(IEnumerable<PackageVersion> vitems)
        {
            if (vitems.Count() == 0) return;
            NuGetVersion upper = null;
            NuGetVersion lower = null;
            if (Lower!=null) lower = new NuGetVersion(Lower);
            if (Upper!=null) upper = new NuGetVersion(Upper);

            // Assert.True(items.All(p=>p.Id == id));
            long commitMax = 0;
            foreach (var p in vitems)
            {
                if (items.Contains(p)) continue;

                if (upper == null) upper = p.NugetVersion;
                else if ( upper < p.NugetVersion) upper = p.NugetVersion;

                if (lower == null) lower = p.NugetVersion;
                else if (lower > p.NugetVersion) lower = p.NugetVersion;

                if (p.CommitNId > commitMax) commitMax = p.CommitNId;
                items.Add(p);
            }
            Upper = upper.ToFullString();
            Lower = lower.ToFullString();
            CommitId = commitMax.ToString();
        }

        /// <summary>
        /// The highest SemVer 2.0.0 version in the page (inclusive)
        /// </summary>
        /// <value></value>
        [JsonProperty("upper"), JsonRequired]
        public string Upper { get; private set; }
        /// <summary>
        /// The lowest SemVer 2.0.0 version in the page (inclusive)
        /// </summary>
        /// <value></value>
        [JsonProperty("lower"), JsonRequired]
        public string Lower { get; private set; }

        /// <summary>
        /// The URL to the registration index
        /// </summary>
        /// <value></value>
        [JsonProperty("parent")]
        public string Parent { get; set; }

        [JsonProperty("count")]
        public int Count { get => items.Count; }
        public string CommitId { get; internal set; }
        public DateTime CommitTimeStamp { get; internal set; }
    }
}