using System;
using System.Collections.Generic;

namespace SourceGit.Models
{
    public enum CommitSearchMethod
    {
        BySHA = 0,
        ByAuthor,
        ByCommitter,
        ByMessage,
        ByPath,
        ByContent,
    }

    public class Commit
    {
        public string SHA { get; set; } = string.Empty;
        public User Author { get; set; } = User.Invalid;
        public ulong AuthorTime { get; set; } = 0;
        public User Committer { get; set; } = User.Invalid;
        public ulong CommitterTime { get; set; } = 0;
        public string Subject { get; set; } = string.Empty;
        public List<string> Parents { get; set; } = new();
        public List<Decorator> Decorators { get; set; } = new();

        public bool IsMerged { get; set; } = false;
        public int Color { get; set; } = 0;
        public double LeftMargin { get; set; } = 0;

        public bool IsCommitterVisible => !Author.Equals(Committer) || AuthorTime != CommitterTime;
        public bool IsCurrentHead => Decorators.Find(x => x.Type is DecoratorType.CurrentBranchHead or DecoratorType.CurrentCommitHead) != null;
        public bool HasDecorators => Decorators.Count > 0;
        public string FirstParentToCompare => Parents.Count > 0 ? $"{SHA}^" : EmptyTreeHash.Guess(SHA);

        public string GetFriendlyName()
        {
            var branchDecorator = Decorators.Find(x => x.Type is DecoratorType.LocalBranchHead or DecoratorType.RemoteBranchHead);
            if (branchDecorator != null)
                return branchDecorator.Name;

            var tagDecorator = Decorators.Find(x => x.Type is DecoratorType.Tag);
            if (tagDecorator != null)
                return tagDecorator.Name;

            return SHA[..10];
        }

        public void ParseParents(string data)
        {
            if (data.Length < 8)
                return;

            Parents.AddRange(data.Split(' ', StringSplitOptions.RemoveEmptyEntries));
        }

        public void ParseDecorators(string data)
        {
            if (data.Length < 3)
                return;

            var subs = data.Split(',', StringSplitOptions.RemoveEmptyEntries);
            foreach (var sub in subs)
            {
                var d = sub.Trim();
                if (d.EndsWith("/HEAD", StringComparison.Ordinal))
                    continue;

                if (d.StartsWith("tag: refs/tags/", StringComparison.Ordinal))
                {
                    Decorators.Add(new Decorator()
                    {
                        Type = DecoratorType.Tag,
                        Name = d.Substring(15),
                    });
                }
                else if (d.StartsWith("HEAD -> refs/heads/", StringComparison.Ordinal))
                {
                    IsMerged = true;
                    Decorators.Add(new Decorator()
                    {
                        Type = DecoratorType.CurrentBranchHead,
                        Name = d.Substring(19),
                    });
                }
                else if (d.Equals("HEAD"))
                {
                    IsMerged = true;
                    Decorators.Add(new Decorator()
                    {
                        Type = DecoratorType.CurrentCommitHead,
                        Name = d,
                    });
                }
                else if (d.StartsWith("refs/heads/", StringComparison.Ordinal))
                {
                    Decorators.Add(new Decorator()
                    {
                        Type = DecoratorType.LocalBranchHead,
                        Name = d.Substring(11),
                    });
                }
                else if (d.StartsWith("refs/remotes/", StringComparison.Ordinal))
                {
                    Decorators.Add(new Decorator()
                    {
                        Type = DecoratorType.RemoteBranchHead,
                        Name = d.Substring(13),
                    });
                }
            }

            Decorators.Sort((l, r) =>
            {
                var delta = (int)l.Type - (int)r.Type;
                if (delta != 0)
                    return delta;
                return NumericSort.Compare(l.Name, r.Name);
            });
        }
    }

    public class CommitFullMessage
    {
        public string Message { get; set; } = string.Empty;
        public InlineElementCollector Inlines { get; set; } = new();
    }
}
