using System;
using System.Collections.Generic;

// ReSharper disable MemberCanBePrivate.Global

namespace NodePipeline.Engine.Abstractions;

/// <summary>
///     Node name settings.
/// </summary>
public static class NodeNamePrefixSettings
{
    private static readonly Dictionary<string, string> NodeNameCache = new();
    private static readonly HashSet<string> PrefixesCache = new();

    /// <summary>
    ///     List of node name prefix to trim
    /// </summary>
    public static IReadOnlyCollection<string> Prefixes => PrefixesCache;

    /// <summary>
    ///     Adds prefix to list
    /// </summary>
    /// <param name="prefix"></param>
    public static void SetNodePrefix(string prefix)
    {
        if (string.IsNullOrWhiteSpace(prefix)) return;
        PrefixesCache.Add(string.Concat(TrimPrefix(prefix, "global::").TrimEnd('.'), "."));
    }

    /// <summary>
    ///     Adds list of node prefixes
    /// </summary>
    /// <param name="prefixes"></param>
    public static void SetNodePrefixes(IEnumerable<string> prefixes)
    {
        foreach (var prefix in prefixes) SetNodePrefix(prefix);
    }

    /// <summary>
    ///     Return node type without specified prefix
    /// </summary>
    public static string TrimNodeType(string nodeType)
    {
        if (string.IsNullOrEmpty(nodeType)) return nodeType;
        if (NodeNameCache.TryGetValue(nodeType, out var name)) return name;
        foreach (var prefix in PrefixesCache)
        {
            if (!nodeType.StartsWith(prefix, StringComparison.Ordinal)) continue;
            var result = nodeType.Substring(prefix.Length);
            NodeNameCache[nodeType] = result;
            return result;
        }

        NodeNameCache[nodeType] = nodeType;
        return nodeType;
    }

    private static string TrimPrefix(string name, string prefix)
    {
        if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(prefix)
                                       || name.Length < prefix.Length)
            return name;

        return name.StartsWith(prefix, StringComparison.Ordinal)
            ? name.Substring(prefix.Length, name.Length - prefix.Length)
            : name;
    }
}