using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Pixiview.Resources
{
    public class ResourceHelper
    {
        public static string Title => GetResource(nameof(Title));
        public static string Guest => GetResource(nameof(Guest));
        public static string Ok => GetResource(nameof(Ok));
        public static string Cancel => GetResource(nameof(Cancel));
        public static string Yes => GetResource(nameof(Yes));
        public static string No => GetResource(nameof(No));
        public static string R18 => GetResource(nameof(R18));
        public static string SyncNo => GetResource(nameof(SyncNo));
        public static string SyncPrompt => GetResource(nameof(SyncPrompt));
        public static string SyncAuto => GetResource(nameof(SyncAuto));
        public static string Operation => GetResource(nameof(Operation));
        public static string SaveOriginal => GetResource(nameof(SaveOriginal));
        public static string Share => GetResource(nameof(Share));
        public static string UserDetail => GetResource(nameof(UserDetail));
        public static string RelatedIllusts => GetResource(nameof(RelatedIllusts));
        public static string SaveSuccess => GetResource(nameof(SaveSuccess));
        public static string AlreadySavedQuestion => GetResource(nameof(AlreadySavedQuestion));
        public static string InvalidUrl => GetResource(nameof(InvalidUrl));
        public static string Favorites => GetResource(nameof(Favorites));
        public static string FavoritesOperation => GetResource(nameof(FavoritesOperation));
        public static string FavoritesReplace => GetResource(nameof(FavoritesReplace));
        public static string FavoritesCombine => GetResource(nameof(FavoritesCombine));
        public static string ExportVideo => GetResource(nameof(ExportVideo));
        public static string CantExportVideo => GetResource(nameof(CantExportVideo));
        public static string AlreadySavedVideo => GetResource(nameof(AlreadySavedVideo));
        public static string ExportSuccess => GetResource(nameof(ExportSuccess));
        public static string FailedResponse => GetResource(nameof(FailedResponse));
        public static string ConfirmSyncFavorite => GetResource(nameof(ConfirmSyncFavorite));
        public static string ConfirmLogin => GetResource(nameof(ConfirmLogin));

        static readonly Dictionary<string, LanguageResource> dict = new Dictionary<string, LanguageResource>();

        public static string GetResource(string name, params object[] args)
        {
            if (!dict.TryGetValue(App.CurrentCulture.PlatformString, out LanguageResource lang))
            {
                lang = new LanguageResource(App.CurrentCulture);
                dict.Add(App.CurrentCulture.PlatformString, lang);
            }

            if (args == null || args.Length == 0)
            {
                return lang[name];
            }
            return string.Format(lang[name], args);
        }

        private class LanguageResource
        {
            private readonly Dictionary<string, string> strings;

            public string this[string key]
            {
                get
                {
                    if (strings != null && strings.TryGetValue(key, out string val))
                    {
                        return val;
                    }
                    return key;
                }
            }

            public LanguageResource(PlatformCulture lang)
            {
                try
                {
#if __IOS__
                    var langId = $"Pixiview.iOS.Resources.Languages.{lang.Language}.xml";
                    var langCodeId = $"Pixiview.iOS.Resources.Languages.{lang.LanguageCode}.xml";
#elif __ANDROID__
                    var langId = $"Pixiview.Droid.Resources.Languages.{lang.Language}.xml";
                    var langCodeId = $"Pixiview.Droid.Resources.Languages.{lang.LanguageCode}.xml";
#endif
                    var assembly = IntrospectionExtensions.GetTypeInfo(typeof(LanguageResource)).Assembly;
                    var names = assembly.GetManifestResourceNames();
                    var name = names.FirstOrDefault(n
                        => string.Equals(n, langId, StringComparison.OrdinalIgnoreCase)
                        || string.Equals(n, langCodeId, StringComparison.OrdinalIgnoreCase));
                    if (name == null)
                    {
#if __IOS__
                        name = "Pixiview.iOS.Resources.Languages.zh-CN.xml";
#elif __ANDROID__
                        name = "Pixiview.Droid.Resources.Languages.zh-CN.xml";
#endif
                    }
                    var xml = new XmlDocument();
                    using (var stream = assembly.GetManifestResourceStream(name))
                    {
                        xml.Load(stream);
                    }
                    strings = new Dictionary<string, string>();
                    foreach (XmlElement ele in xml.DocumentElement) // .Root.Elements()
                    {
                        strings[ele.Name] = ele.InnerText;  // .LocalName   Value
                    }
                }
                catch (Exception ex)
                {
                    // load failed
                    App.DebugError("language.ctor", $"failed to load xml resource: {ex.Message}");
                }
            }
        }
    }

    [ContentProperty(nameof(Text))]
    public class TextExtension : IMarkupExtension
    {
        public string Text { get; set; }

        public object ProvideValue(IServiceProvider serviceProvider)
        {
            if (Text == null)
            {
                return string.Empty;
            }
            return ResourceHelper.GetResource(Text);
        }
    }
}
