using System.Text;
using System.Text.RegularExpressions;

namespace ZelWiki.Library
{
    public class NamespaceNavigation
    {
        private string _namespace = string.Empty;
        private string _page = string.Empty;
        private readonly bool _lowerCase = false;

        public string Namespace
        {
            get => _namespace;
            set => _namespace = CleanAndValidate(value.Replace("::", "_")).Trim();
        }

        public string Page
        {
            get => _page;
            set => _page = CleanAndValidate(value.Replace("::", "_")).Trim();
        }

        public string Canonical
        {
            get
            {
                if (string.IsNullOrWhiteSpace(Namespace))
                {
                    return Page;
                }

                return $"{Namespace}::{Page}";
            }
            set
            {
                var cleanedAndValidatedValue = CleanAndValidate(value, _lowerCase);

                var parts = cleanedAndValidatedValue.Split("::");
                if (parts.Length < 2)
                {
                    Page = parts[0].Trim();
                }
                else
                {
                    Namespace = parts[0].Trim();
                    Page = string.Join("_", parts.Skip(1).Select(o => o.Trim())).Trim();
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="givenCanonical"></param>
        public NamespaceNavigation(string givenCanonical)
        {
            _lowerCase = true;
            Canonical = givenCanonical;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="givenCanonical"></param>
        /// <param name="lowerCase"></param>
        public NamespaceNavigation(string givenCanonical, bool lowerCase)
        {
            _lowerCase = lowerCase;
            Canonical = givenCanonical;
        }

        public override string ToString()
        {
            return Canonical;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="str"></param>
        /// <param name="lowerCase"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static string CleanAndValidate(string? str, bool lowerCase = true)
        {
            if (str == null)
            {
                return string.Empty;
            }

            str = str.Trim().Trim([':']).Trim();

            if (str.Contains("::"))
            {
                var parts = str.Split("::");
                if (parts.Length != 2)
                {
                    throw new Exception("导航不能包含多个命名空间");
                }

                return $"{CleanAndValidate(parts[0].Trim())}::{CleanAndValidate(parts[1].Trim(), lowerCase)}";
            }

            str = str.Replace("&quot;", "\"")
                .Replace("&amp;", "&")
                .Replace("&lt;", "<")
                .Replace("&gt;", ">")
                .Replace("&nbsp;", " ");

            str = str.Replace('\\', '/');

            var sb = new StringBuilder();
            foreach (var c in str)
            {
                if (char.IsWhiteSpace(c) || c == '.')
                {
                    sb.Append('_');
                }
                else if (char.IsLetterOrDigit(c) || c == '_' || c == '/' || c == '-')
                {
                    sb.Append(c);
                }
            }

            var result = sb.ToString();

            result = Regex.Replace(result, @"[_]{2,}", "_");
            result = Regex.Replace(result, @"[/]{2,}", "/");


            return lowerCase ? result.TrimEnd(['/', '\\']).ToLowerInvariant() : result.TrimEnd(['/', '\\']);
        }
    }
}