using System;
using System.ComponentModel;
using System.Threading.Tasks;
using TINK.Model.Device;
using TINK.Services.CopriApi.ServerUris;
using Xamarin.Essentials;
using Xamarin.Forms;

namespace TINK.ViewModel.Info
{
    /// <summary> Manges the tabbed info page. </summary>
    public class InfoViewModel : INotifyPropertyChanged
    {
        /// <summary> Fired whenever a property changed.</summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary> Holds the name of the host.</summary>
        private string HostName { get; }

        /// <summary> Holds value wether site caching is on or off.</summary>
        bool IsSiteCachingOn { get; }

        /// <summary> Constructs Info view model</summary>
        /// <param name="isSiteCachingOn">Holds value wether site caching is on or off.</param>
        /// <param name="resourceProvider">Delegate to get an an embedded html ressource. Used as fallback if download from web page does not work and cache is empty.</param>
        public InfoViewModel(
            string hostName,
             bool isSiteCachingOn,
            Func<string, string> resourceProvider)
        {
            HostName = hostName;

            IsSiteCachingOn = isSiteCachingOn;

            InfoAgb = new HtmlWebViewSource { Html = "<html>Loading...</html>" };

            ResourceProvider = resourceProvider
                ?? throw new ArgumentException($"Can not instantiate {typeof(InfoViewModel)}-object. No ressource provider availalbe.");
        }

        /// <summary> Called when page is shown. </summary>
        public async void OnAppearing()
        {
            InfoAgb = await GetAgb(HostName, IsSiteCachingOn, ResourceProvider);

            InfoPrivacy = new HtmlWebViewSource
            {
                Html = await ViewModelHelper.GetSource(
                    $"https://{HostName}/{HostName.GetPrivacyResource()}",
                    IsSiteCachingOn,
                    HostName.GetIsCopri() ? () => ResourceProvider("HtmlResouces.V02.InfoDatenschutz.html") : (Func<string>) null) /* offline resources only available for TINK */,
            };

            InfoImpressum = new HtmlWebViewSource
            {
                Html = HostName.GetIsCopri()
                    ? ResourceProvider("HtmlResouces.V02.InfoImpressum.html")
                    : await ViewModelHelper.GetSource($"https://{HostName}/{CopriHelper.SHAREE_SILTEFOLDERNAME}/impress.html", IsSiteCachingOn)
            };
        }

        /// <summary> Gets the AGBs</summary>
        /// <param name="resourceProvider"></param>
        /// <returns> AGBs</returns>
        public static async Task<HtmlWebViewSource> GetAgb(
            string hostName,
            bool isSiteCachingOn,
            Func<string, string> resourceProvider)
        {
            return new HtmlWebViewSource
            {
                Html = await ViewModelHelper.GetSource(
                            $"https://{hostName}/{hostName.GetAGBResource()}",
                            isSiteCachingOn,
                            hostName.GetIsCopri() ? () => resourceProvider("HtmlResouces.V02.InfoAGB.html") : (Func<string>) null) /* offline resources only available for TINK */,
            };
        }

        /// <summary> Gets the platfrom specific prefix. </summary>
        private Func<string, string> ResourceProvider { get; set; }

        /// <summary> Gets the app related information (app version and licenses). </summary>
        public HtmlWebViewSource InfoLicenses => new HtmlWebViewSource
        {
            Html = ResourceProvider("HtmlResouces.V02.InfoLicenses.html")
                .Replace("CURRENT_VERSION_TINKAPP", DependencyService.Get<IAppInfo>().Version.ToString())
                .Replace("ACTIVE_APPNAME", AppInfo.Name)
        };

        /// <summary> Privacy text.</summary>
        private HtmlWebViewSource infoImpress;
        /// <summary> Gets the privacy related information. </summary>
        public  HtmlWebViewSource InfoImpressum
        {
            get => infoImpress;
            set
            {
                infoImpress = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(InfoImpressum)));
            }
        }

        /// <summary> Agb information text.</summary>
        private HtmlWebViewSource infoAgb;

        /// <summary> Privacy text.</summary>
        private HtmlWebViewSource infoPrivacy;

        /// <summary> Agb information text.</summary>
        public HtmlWebViewSource InfoAgb
        {
            get => infoAgb;
            set
            {
                infoAgb = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(InfoAgb)));
            }
        }

        /// <summary> Agb information text.</summary>
        public HtmlWebViewSource InfoPrivacy
        {
            get => infoPrivacy;
            set
            {
                infoPrivacy = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(InfoPrivacy)));
            }
        }
    }
}