using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using CefSharpWrap.CustomResource;

namespace CefSharpWrap.AceEditorWrap.Resources
{
    internal static class EmbeddedResourceManager
    {
        private static readonly string MyNameSpaceFull = typeof(EmbeddedResourceManager).Namespace;
        private static IReadOnlyDictionary<string, byte[]> CachedBinResource { get; }

        internal static ICustomResourceResolver ResourceResolver { get; }

        static EmbeddedResourceManager()
        {
            var assembly = Assembly.GetExecutingAssembly();
            CachedBinResource = assembly.GetManifestResourceNames()
                .Where(p => p.StartsWith(MyNameSpaceFull))
                .ToDictionary(p => p, p => assembly.GetManifestResourceStream(p).ToBytes());


            ResourceResolver = new EmbeddedResourceResolver();

        }

        private class EmbeddedResourceResolver : ICustomResourceResolver
        {
            public ICustomResourceResolveResult Resolve(string path)
            {
                var binResource = GetBinResource(path);
                return binResource == null
                    ? null
                    : new DefaultCustomResourceResolveResult(Path.GetFileName(path), new BytesProvider(binResource));
            }
        }

        private static byte[] ToBytes(this Stream me)
        {
            using (var tmp = new MemoryStream())
            {
                me.CopyTo(tmp);
                return tmp.ToArray();
            }
        }

        private static byte[] GetBinResource(string path)
        {
            path = path.TrimStart('/');

#if DEBUG
            if (path == "AceEditorPage.html")
            {
                var localFile = Path.Combine(CefSharpAceEditorDebugSupport.LocalResourceDir, path);
                return File.ReadAllBytes(localFile);
            }
#endif

            var resName = path.Replace("/", ".");
            return CachedBinResource.TryGetValue($"{MyNameSpaceFull}.{resName}", out var bin) ? bin : null;
        }
    }
}