#if UNITY_STANDALONE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using _Core;
using _Core.Storage;
using Newtonsoft.Json;
using Seayoo.ComboSDK.Windows;

namespace _Combo
{

    public class LastAnnouncementInfo
    {
        public long LastTime { get; set; }
        public int LastLevel { get; set; }
    }

    internal class AnnouncementManager : Singleton<AnnouncementManager>
    {
        private Action<ComboResult<ComboSDKCheckAnnouncementsResult>> checkAnnouncementsResult;
        private Action<ComboResult<ComboSDKOpenAnnouncementsResult>> openAnnouncesResult;
        private const string checkAnnouncementsPrefKey = "combosdk_check_announcement";
        private string gameId = "";
        private string distro = "";
        private const string defaultProfile = "#SHARED";
        private ComboSDKOpenAnnouncementsOptions lastOptions;

        public void Setup(string gameId, string distro)
        {
            EventSystem.Register(this);
            this.gameId = gameId;
            this.distro = distro;
        }

        public void CheckAnnouncements(ComboSDKCheckAnnouncementsOptions opts, Action<ComboResult<ComboSDKCheckAnnouncementsResult>> action)
        {
            checkAnnouncementsResult = action;
            LastAnnouncementInfo lastAnnouncementInfo = new LastAnnouncementInfo();
            if (UserPrefs.HasKey(checkAnnouncementsPrefKey))
            {
                var jsonString = UserPrefs.GetString(checkAnnouncementsPrefKey);
                var lastAnnouncementInfoDic = JsonConvert.DeserializeObject<Dictionary<string, LastAnnouncementInfo>>(jsonString);
                string profile = "";
                if(string.IsNullOrEmpty(opts.Profile))
                {
                    profile = defaultProfile;
                }
                else
                {
                    profile = opts.Profile;
                }
                lastAnnouncementInfoDic.TryGetValue(profile, out lastAnnouncementInfo);
            }
            ComboClient.CheckAnnouncements(result =>{
                if(result.IsSuccess)
                {
                    checkAnnouncementsResult?.Invoke(ComboResult<ComboSDKCheckAnnouncementsResult>.CreateSuccess(new ComboSDKCheckAnnouncementsResult
                    {
                        NewAnnouncementsAvailable = result.Data.newAnnouncementsAvailable
                    }));
                }
                else
                {
                    checkAnnouncementsResult?.Invoke(ComboResult<ComboSDKCheckAnnouncementsResult>.CreateFail(result.Error));
                }
            }, (error) =>{
                checkAnnouncementsResult?.Invoke(ComboResult<ComboSDKCheckAnnouncementsResult>.CreateFail(error));
            }, (int?)lastAnnouncementInfo?.LastTime, lastAnnouncementInfo?.LastLevel, Combo.Instance.GetLoginInfo().comboId, opts.Level);
        }

        public void OpenAnnouncements(ComboSDKOpenAnnouncementsOptions opts, Action<ComboResult<ComboSDKOpenAnnouncementsResult>> action)
        {
            openAnnouncesResult = action;
            lastOptions = opts;
            if(string.IsNullOrEmpty(GlobalParameters.Instance.GameAnnouncementsUrl))
            {
                var invalidArgumentsError = new InvalidArgumentsError("announcement", errorType : InvalidArgumentsErrorType.INVALID_ANNOUNCEMENTS_URL);
                var error = new InternalError(I18n.T("announcements_url_error"), invalidArgumentsError);
                openAnnouncesResult?.Invoke(ComboResult<ComboSDKOpenAnnouncementsResult>.CreateFail(error));
                return;
            }
            try
            {
                UIController.Instance.ShowWebView(GetUrl(opts.Level.ToString()), WebViewType.Announcement, opts.Width, opts.Height, false, backgroundEnable: true, dragMode: Vuplex.WebView.DragMode.DragToScroll);
            }
            catch(InternalError error)
            {
                openAnnouncesResult?.Invoke(ComboResult<ComboSDKOpenAnnouncementsResult>.CreateFail(error));
            }
        }

        [EventSystem.BindEvent]
        public void LoadAnnouncementFailed(LoadFailed evt)
        {
            if(evt.webViewType != WebViewType.Announcement)
            {
                return;
            }
            var error = new InternalError(I18n.T("announcements_open_error"));
            openAnnouncesResult?.Invoke(ComboResult<ComboSDKOpenAnnouncementsResult>.CreateFail(error));
        }

        [EventSystem.BindEvent]
        public void LoadAnnouncementSuccess(LoadSuccess evt)
        {
            if(evt.webViewType != WebViewType.Announcement)
            {
                return;
            }
            string profile = "";
            if(string.IsNullOrEmpty(lastOptions.Profile))
            {
                profile = defaultProfile;
            }
            else
            {
                profile = lastOptions.Profile;
            }
            SaveLastAnnouncementInfo(profile, lastOptions.Level);
            openAnnouncesResult?.Invoke(ComboResult<ComboSDKOpenAnnouncementsResult>.CreateSuccess(new ComboSDKOpenAnnouncementsResult()));
        }

        private string GetUrl(string level = null)
        { 
            var queryParameters = new Dictionary<string, string>
            {
                { "game_id", gameId },
                { "distro", distro },
                { "lang", I18n.GetLanguageCode()}
            };
            string comboId = Combo.Instance.GetLoginInfo().comboId;
            if(!string.IsNullOrEmpty(comboId))
            {
                queryParameters.Add("comboId", comboId);
            }
            if(!string.IsNullOrEmpty(level))
            {
                queryParameters.Add("level", level.ToString());
            }
            string queryParametersStr = string.Join("&", queryParameters.Select(kv => $"{kv.Key}={WebUtility.UrlEncode(kv.Value)}"));
            return $"{GlobalParameters.Instance.GameAnnouncementsUrl}?{queryParametersStr}";
        }

        private void SaveLastAnnouncementInfo(string profile, int level)
        {
            var jsonString = UserPrefs.GetString(checkAnnouncementsPrefKey);
            var lastAnnouncementInfoDic = JsonConvert.DeserializeObject<Dictionary<string, LastAnnouncementInfo>>(jsonString);
            if(lastAnnouncementInfoDic == null)
            {
                lastAnnouncementInfoDic = new Dictionary<string, LastAnnouncementInfo>();
            }
            if(lastAnnouncementInfoDic.ContainsKey(profile))
            {
                lastAnnouncementInfoDic[profile] = new LastAnnouncementInfo
                {
                    LastTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
                    LastLevel = level
                };
            }
            else
            {
                lastAnnouncementInfoDic.Add(profile, new LastAnnouncementInfo
                {
                    LastTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
                    LastLevel = level
                });
            }
            UserPrefs.SetString(checkAnnouncementsPrefKey, JsonConvert.SerializeObject(lastAnnouncementInfoDic));
        }
    }
}
#endif