using System;
using Emby.Naming.Common;
namespace Emby.Naming.Video
{
    /// 
    /// Parse 3D format related flags.
    /// 
    public static class Format3DParser
    {
        // Static default result to save on allocation costs.
        private static readonly Format3DResult _defaultResult = new(false, null);
        /// 
        /// Parse 3D format related flags.
        /// 
        /// Path to file.
        /// The naming options.
        /// Returns  object.
        public static Format3DResult Parse(ReadOnlySpan path, NamingOptions namingOptions)
        {
            int oldLen = namingOptions.VideoFlagDelimiters.Length;
            Span delimiters = stackalloc char[oldLen + 1];
            namingOptions.VideoFlagDelimiters.AsSpan().CopyTo(delimiters);
            delimiters[oldLen] = ' ';
            return Parse(path, delimiters, namingOptions);
        }
        private static Format3DResult Parse(ReadOnlySpan path, ReadOnlySpan delimiters, NamingOptions namingOptions)
        {
            foreach (var rule in namingOptions.Format3DRules)
            {
                var result = Parse(path, rule, delimiters);
                if (result.Is3D)
                {
                    return result;
                }
            }
            return _defaultResult;
        }
        private static Format3DResult Parse(ReadOnlySpan path, Format3DRule rule, ReadOnlySpan delimiters)
        {
            bool is3D = false;
            string? format3D = null;
            // If there's no preceding token we just consider it found
            var foundPrefix = string.IsNullOrEmpty(rule.PrecedingToken);
            while (path.Length > 0)
            {
                var index = path.IndexOfAny(delimiters);
                if (index == -1)
                {
                    index = path.Length - 1;
                }
                var currentSlice = path[..index];
                path = path[(index + 1)..];
                if (!foundPrefix)
                {
                    foundPrefix = currentSlice.Equals(rule.PrecedingToken, StringComparison.OrdinalIgnoreCase);
                    continue;
                }
                is3D = foundPrefix && currentSlice.Equals(rule.Token, StringComparison.OrdinalIgnoreCase);
                if (is3D)
                {
                    format3D = rule.Token;
                    break;
                }
            }
            return is3D ? new Format3DResult(true, format3D) : _defaultResult;
        }
    }
}