using CefSharp;
using CefSharp.WinForms;
using CefSharpWrap.CustomResource;
using System;
using System.IO;
using System.Reflection;

namespace CefSharpWrap
{
    public static class CefSharpWrapFactory
    {
        public static readonly string SchemeName = $"{nameof(CefSharpWrap)}-{Guid.NewGuid()}".ToLower();
        public static readonly string CustomResourceDomainName = $"app-{Guid.NewGuid()}";

        static CefSharpWrapFactory()
        {
            var myPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            InitInternal(myPath);
        }

        private static void InitInternal(string cefNativeLibraryPath)
        {
            CefSharpSettings.LegacyJavascriptBindingEnabled = true;

            var settings = new CefSettings();

            settings.BrowserSubprocessPath = Path.Combine(cefNativeLibraryPath, settings.BrowserSubprocessPath);
            settings.CachePath = cefNativeLibraryPath;

            settings.LogSeverity = LogSeverity.Disable;
            settings.CefCommandLineArgs.Add("-incognito", "");
            settings.CefCommandLineArgs.Add("--disable-application-cache", "");
            settings.CefCommandLineArgs.Add("--disable-cache", "");
            settings.CefCommandLineArgs.Add("--disable-gpu-program-cache", "");
            settings.CefCommandLineArgs.Add("--disable-gpu-shader-disk-cache", "");
            settings.CefCommandLineArgs.Add("--disable-local-storage", "");

            settings.RegisterScheme(new CefCustomScheme
            {
                SchemeName = SchemeName,
                DomainName = CustomResourceDomainName,
                SchemeHandlerFactory = new CustomResourceSchemeHandlerFactory(),
            });

            Cef.Initialize(settings);

            //TODO: 启动收尸子进程
        }

        public static void AddCustomResource(string path, string mime, IBytesProvider provider, ConflictResolve conflictResolve = ConflictResolve.Error)
        {
            var pathIsExisted = CustomResourceSchemeHandlerFactory.PathResources.ContainsKey(path);
            if (false == pathIsExisted || ConflictResolve.Override == conflictResolve) CustomResourceSchemeHandlerFactory.PathResources[path] = new Tuple<string, IBytesProvider>(mime, provider);
            else if (conflictResolve == ConflictResolve.Error) throw new ArgumentException("Path already exist", nameof(path));
        }

        public static void AddCustomResourceResolver(string pathPrefix, ICustomResourceResolver resolver, ConflictResolve conflictResolve = ConflictResolve.Error)
        {
            var pathIsExisted = CustomResourceSchemeHandlerFactory.PathPrefixResolvers.ContainsKey(pathPrefix);
            if (false == pathIsExisted || ConflictResolve.Override == conflictResolve) CustomResourceSchemeHandlerFactory.PathPrefixResolvers[pathPrefix] = resolver;
            else if (conflictResolve == ConflictResolve.Error) throw new ArgumentException("Path prefix already exist", nameof(pathPrefix));
        }

        public static bool RemoveCustomResource(string path)
        {
            return CustomResourceSchemeHandlerFactory.PathResources.TryRemove(path, out _);
        }

        public static CefSharpWrapBrowser CreateSealedInstance(string url)
        {
            return new CefSharpWrapBrowser(false, url);
        }

        public static CefSharpWrapBrowser CreateLocalFileAccessInstance(string path)
        {
            return new CefSharpWrapBrowser(true, path);
        }

        public static void Shutdown()
        {
            Cef.Shutdown();
        }
    }
}
