using System;
using System.Json;
using System.Net.Http;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.IO;

using Foundation;
using UIKit;

using Xamarin.Forms;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
using System.Globalization;

[assembly: Xamarin.Forms.Dependency(typeof(InABox.Mobile.iOS.Version_iOS))]
namespace InABox.Mobile.iOS
{

    internal static class iOS_VersionExtensions
    {
        public static string MakeSafeForAppStoreShortLinkUrl(this string value)
        {
            // Reference: https://developer.apple.com/library/content/qa/qa1633/_index.html

            var regex = new Regex(@"[©™®!¡""#$%'()*+,\\\-.\/:;<=>¿?@[\]^_`{|}~]*");

            var safeValue = regex.Replace(value, "")
                                 .Replace(" ", "")
                                 .Replace("&", "and")
                                 .ToLower();

            return safeValue;
        }
    }

    /// <summary>
    /// <see cref="ILatestVersion"/> implementation for iOS.
    /// </summary>
    public class Version_iOS : IAppVersion
    {
        string _bundleName => NSBundle.MainBundle.ObjectForInfoDictionary("CFBundleName").ToString();
        string _bundleIdentifier => NSBundle.MainBundle.ObjectForInfoDictionary("CFBundleIdentifier").ToString();
        string _bundleVersion => NSBundle.MainBundle.ObjectForInfoDictionary("CFBundleShortVersionString").ToString();
        JsonValue _appstoreInfo = null;

        /// <inheritdoc />
        public string InstalledVersionNumber
        {
            get => _bundleVersion;
        }


        private async Task CheckAppStoreInfo(string appName)
        {

            if (_appstoreInfo != null)
                return;

            var url = $"http://itunes.apple.com/lookup?bundleId={appName}";

            using (var request = new HttpRequestMessage(HttpMethod.Get, url))
            {
                using (var handler = new HttpClientHandler())
                {

                    handler.ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) =>
                    {
                        //bypass
                        return true;
                    };

                    using (var client = new HttpClient(handler))
                    {
                        using (var responseMsg = await client.SendAsync(request, HttpCompletionOption.ResponseContentRead))
                        {
                            if (!responseMsg.IsSuccessStatusCode)
                            {
                                throw new LatestVersionException($"Error connecting to the App Store. Url={url}.");
                            }

                            try
                            {
                                var content = responseMsg.Content == null ? null : await responseMsg.Content.ReadAsStringAsync();

                                _appstoreInfo = JsonValue.Parse(content);

                                
                            }
                            catch (Exception e)
                            {
                                throw new LatestVersionException($"Error parsing content from the App Store. Url={url}.", e);
                            }
                        }
                    }
                }
            }
        }

        /// <inheritdoc />
        public async Task<bool> IsUsingLatestVersion()
        {
            string latestversion = string.Empty;
            try
            {                
                latestversion = await GetLatestVersionNumber();
                return Version.Parse(latestversion).CompareTo(Version.Parse(_bundleVersion)) <= 0;
            }
            catch (Exception e)
            {
                throw new LatestVersionException($"Error comparing current app version number with latest. Bundle version={_bundleVersion} and lastest version={latestversion} .", e);
            }
        }

        /// <inheritdoc />
        public async Task<string> GetLatestVersionNumber()
        {
            return await GetLatestVersionNumber(_bundleIdentifier);
        }

        /// <inheritdoc />
        public async Task<string> GetLatestVersionNumber(string appName)
        {
            if (string.IsNullOrWhiteSpace(appName))
            {
                throw new ArgumentNullException(nameof(appName));
            }

            await CheckAppStoreInfo(appName);

            var version = _appstoreInfo["results"][0]["version"];

            return version;
        }

        /// <inheritdoc />
        public Task OpenAppInStore()
        {
            return OpenAppInStore(_bundleName);
        }

        /// <inheritdoc />
        public Task OpenAppInStore(string appName)
        {
            if (string.IsNullOrWhiteSpace(appName))
            {
                throw new ArgumentNullException(nameof(appName));
            }

            try
            {

                var location = RegionInfo.CurrentRegion.Name.ToLower();
                var trackid = _appstoreInfo["results"][0]["trackId"];

                var url = String.Format("https://itunes.apple.com/{0}/app/{1}/id{2}?mt=8",location,appName,trackid);

                //appName = appName.MakeSafeForAppStoreShortLinkUrl();

#if __IOS__
                
                UIKit.UIApplication.SharedApplication.OpenUrl(new NSUrl(url)); // $"http://appstore.com/{appName}"));
#elif __MACOS__
                AppKit.NSWorkspace.SharedWorkspace.OpenUrl(new NSUrl($"http://appstore.com/mac/{appName}"));
#endif

                return Task.FromResult(true);
            }
            catch (Exception e)
            {
                throw new LatestVersionException($"Unable to open {appName} in App Store.", e);
            }
        }
    }
}