namespace Guru
{
    using System;
    using System.Collections.Generic;
    using UnityEngine;
    
    /// 
    /// 打点管理
    /// 
    public partial class GuruSDK
    {
        #region 通用接口
        /// 
        /// 自定义事件打点
        /// 
        /// 
        /// 
        /// 
        public static void LogEvent(string eventName, Dictionary data = null, int priority = -1)
        {
            if(priority < 0) priority = GetEventPriorityInt(eventName);
            Analytics.Track(eventName, data, null, priority);
        }
        public static void SetScreen(string screen, string extra = "")
        {
            if (!IsInitialSuccess)
            {
                UnityEngine.Debug.LogWarning($"{Tag} :: SetScreen {screen} can not be set before SDK init!");
                return;
            }
            Analytics.SetCurrentScreen(screen, extra);
        }
        #endregion
        
        #region 设置用户属性
        /// 
        /// 设置用户属性
        /// 
        /// 
        /// 
        public static void SetUserProperty(string key, string value)
        {
            Analytics.SetUserProperty(key, value);
        }
        public static void SetUID(string uid)
        {
            Analytics.SetUid(uid);
        }
        public static void SetUserBLevel(int bLevel)
        {
            if (!InitConfig.AutoRecordFinishedLevels)
            {
                Model.SetBLevelValue(bLevel);
                Analytics.BLevel = bLevel;
            }
            Analytics.SetBLevel(bLevel);
        }
        
        public static void SetUserBPlay(int bPlay)
        {
            if (!InitConfig.AutoRecordFinishedLevels)
            {
                Model.SetBPlayValue(bPlay);
                Analytics.BPlay = bPlay;
            }
            Analytics.SetBPlay(bPlay);
        }
        
        /// 
        /// 上报用户全部的 Coin (当前值)
        /// 
        /// 
        public static void SetUserCoin(int coins)
        {
            SetUserProperty(Consts.PropertyCoin, $"{coins}");        
        }
        
        /// 
        /// 上报用户免费金币的 数量 (累加值)
        /// 
        /// 
        public static void SetUserNonIapCoin(int freeCoins)
        {
            SetUserProperty(Consts.PropertyNonIAPCoin, $"{freeCoins}");        
        }
        
        /// 
        /// 上报用户付费金币的 数量 (累加值)
        /// 
        /// 
        public static void SetUserIapCoin(int paidCoins)
        {
            SetUserProperty(Consts.PropertyIAPCoin, $"{paidCoins}");        
        }
        
        public static void SetUserExp(int exp)
        {
            SetUserProperty(Consts.PropertyExp, $"{exp}");        
        }
        
        public static void SetUserHp(int hp)
        {
            SetUserProperty(Consts.PropertyHp, $"{hp}");        
        }
        public static void SetUserGrade(int grade)
        {
            SetUserProperty(Consts.PropertyGrade, $"{grade}");        
        }
        public static void SetUserIsIAP(bool isIapUser)
        {
            Analytics.SetIsIapUser(isIapUser);
        }
        public static void SetATTStatus(string status)
        {
            Analytics.SetAttStatus(status);
        }
        
        
        #endregion
        
        #region 游戏打点
        /// 
        /// 游戏启动打点 (level_start)
        /// 
        /// 关卡Id
        /// 关卡名称: main_01_9001,  daily_challenge_81011
        /// 关卡类型: 主线:main
        /// 配置/谜题/图片/自定义Id: 101120
        /// 关卡开始类型: play:开始游戏;replay:重玩;continue:继续游戏
        /// 是否重新开始: true/false
        /// 扩展数据
        public static void LogLevelStart(int levelId, string startType = Consts.EventLevelStartModePlay, 
            string levelType = Consts.LevelTypeMain, string levelName = "", string itemId = "",
            bool isReplay = false, Dictionary extra = null)
        {
            if (!IsInitialSuccess)
            {
                Debug.LogError($"{Tag} :: LogLevelStart {levelId} :: Please call  first, before you call .");
                return;
            }
            Analytics.LogLevelStart(levelId, levelName, levelType, itemId, startType, isReplay, extra);
        }
        /// 
        /// 游戏点击 Continue 继续游戏 (level_start) (continue)
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void LogLevelContinue(int levelId, string levelType = Consts.LevelTypeMain,
            string levelName = "", string itemId = "", Dictionary extra = null)
        {
            LogLevelStart(levelId, Consts.EventLevelStartModeContinue, levelType, levelName, itemId,  true, extra:extra);
        }
        
        /// 
        /// 游戏点击 Replay 重玩关卡 (level_start) (replay)
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void LogLevelReplay(int levelId, string levelType = Consts.LevelTypeMain,
            string levelName = "", string itemId = "", Dictionary extra = null)
        {
            LogLevelStart(levelId, Consts.EventLevelStartModeReplay,levelType, levelName, itemId,  true, extra:extra);
        }
        /// 
        /// 关卡结束打点 (level_end)
        /// 
        /// 关卡Id
        /// success:成功;fail:失败;exit:退出;timeout:超时;replay:重玩...
        /// 关卡类型: 主线:main
        /// 关卡名称: main_01_9001,  daily_challenge_81011
        /// 配置/谜题/图片/自定义Id: 101120
        /// 关卡完成时长(单位:毫秒)
        /// 步数(有则上报)
        /// 分数(有则上报)
        /// 扩展数据
        public static void LogLevelEnd(int levelId, string result = Consts.EventLevelEndSuccess,
            string levelType = Consts.LevelTypeMain, string levelName = "", string itemId = "",
            int duration = 0, int? step = null, int? score = null, Dictionary extra = null)
        {
            if (!IsInitialSuccess)
            {
                Debug.LogError(
                    $"{Tag} :: LogLevelEnd {levelId} :: Please call  first, before you call .");
                return;
            }
            // 优先打 level_end 事件
            Analytics.LogLevelEnd(levelId, result, levelName, levelType, itemId, duration, step, score, extra);
            
            // 自动记录关卡属性
            if (InitConfig.AutoRecordFinishedLevels)
            {
                if (result == Consts.EventLevelEndSuccess)
                {
                    if (levelType.ToLower() == Consts.LevelTypeMain)
                    {
                        if (levelId >= Model.SuccessLevelId) Model.SuccessLevelId = levelId; // 自动记录关卡完成次数
                    }
                    Model.TotalPlayedCount++; // 自动记录关卡总次数
                    Analytics.LevelEndSuccess(Model.TotalPlayedCount); // 自动 level_end_success
                }
                
                Analytics.BLevel = Model.SuccessLevelId; // 记录 BLevel
                Analytics.BPlay = Model.TotalPlayedCount; // 记录 BPlay
            }
           
        }
        /// 
        /// 关卡首次通关
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void LogLevelFirstEnd(string levelType, string levelName, int level,
            string result = Consts.EventLevelEndSuccess, int duration = 0, Dictionary extra = null)
        {
            Analytics.LevelFirstEnd(levelType, levelName, level, result, duration, extra);
        }
        /// 
        /// 关卡总胜利次数打点 (level_end_success_{num})
        /// 
        /// 完成总关数累计值
        /// /// 扩展参数
        public static void LogLevelEndSuccess(int bPlay, Dictionary extra = null)
        {
            if (InitConfig.AutoRecordFinishedLevels) return;
            Analytics.LevelEndSuccess(bPlay, extra);
        }
        /// 
        /// 游戏失败打点 (level_end) (fail)
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void LogLevelFail(int levelId,
            string levelType = Consts.LevelTypeMain, string levelName = "", string itemId = "",
            int duration = 0, int? step = null, int? score = null , Dictionary extra = null)
        {
            LogLevelEnd(levelId, Consts.EventLevelEndFail, levelType, levelName, itemId, duration, step, score, extra);
        }
        /// 
        /// 游戏失败退出 (level_end) (exit) 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void LogLevelFailExit(int levelId,
            string levelType = Consts.LevelTypeMain, string levelName = "", string itemId = "",
            int duration = 0, int? step = null, int? score = null, Dictionary extra = null)
        {
            LogLevelEnd(levelId, Consts.EventLevelEndExit, levelType, levelName, itemId, duration, step, score, extra);
        }
        /// 
        /// 关卡超时失败 (level_end) (timeout) 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void LogLevelFailTimeout(int levelId,
            string levelType = Consts.LevelTypeMain, string levelName = "", string itemId = "",
            int duration = 0, int? step = null, int? score = null, Dictionary extra = null)
        {
            LogLevelEnd(levelId, Consts.EventLevelEndTimeout, levelType, levelName, itemId, duration, step, score, extra);
        }
        /// 
        /// 玩家(角色)升级事件 (level_up)
        /// 
        /// 
        /// 
        /// 扩展数据
        public static void LogLevelUp(int playerLevel, string characterName, Dictionary extra = null)
        {
            if (!IsInitialSuccess)
            {
                Debug.LogError($"{Tag} :: LogLevelUp {playerLevel} :: Please call  first, before you call .");
                return;
            }
            Analytics.LevelUp(playerLevel, characterName, extra);
        }
        /// 
        /// 玩家解锁成就 (unlock_achievement)
        /// 
        /// 
        /// 扩展数据
        public static void LogAchievement(string achievementId, Dictionary extra = null)
        {
            if (!IsInitialSuccess)
            {
                Debug.LogError($"{Tag} :: LogAchievement {achievementId} :: Please call  first, before you call .");
                return;
            }
            Analytics.UnlockAchievement(achievementId, extra);
        }
        /// 
        /// 玩家体力变化 (hp_points)
        /// 
        /// 场景
        /// HP 增量值
        /// HP 初始值
        /// HP 结算值
        /// 额外数据
        public static void LogHpPoints(string scene, int hp, int hpBefore, int hpAfter,
            Dictionary extra = null)
        {
            if (!IsInitialSuccess)
            {
                UnityEngine.Debug.LogError(
                    $"{Tag} :: LogHpPoints {hp} :: Please call  first, before you call .");
                return;
            }
            var dict = new Dictionary()
            {
                [Consts.ParameterItemCategory] = scene,
                ["hp"] = hp,
                ["hp_before"] = hpBefore,
                ["hp_after"] = hpAfter,
            };
            if (extra != null)
            {
                foreach (var k in extra.Keys)
                {
                    dict[k] = extra[k];
                }
            }
            LogEvent(Consts.EventHpPoints, dict);
        }
        #endregion
        
        #region SDK 打点
        
        /// 
        /// Log SDK boost time
        /// 
        /// 
        private static void LogSDKInitTime(double time)
        {
            Analytics.Track(Consts.EventSDKInfo, new Dictionary()
            {
                { "boost_time", time.ToString("F6") },
                { Consts.PropertyDeviceID, DeviceId },
                { "version", Version},
                { "network", Instance.GetNetworkStatus()},
            }, new Analytics.EventSetting()
            {
                EnableFirebaseAnalytics = true,
            });
        }
        /// 
        /// 获取 GuruSDK 实验分组
        /// 
        /// 
        public static string GetGuruExperimentGroupId()
        {
            if (!GuruAnalytics.IsReady) return "not_set";
            return GuruAnalytics.Instance.ExperimentGroupId;
        }
        #endregion
        #region IAP 打点
        private static string TryGetFirstProductId()
        {
            if (GuruSettings.Instance != null && (GuruSettings.Instance.Products?.Length ?? 0) > 0)
            {
                return GuruSettings.Instance.Products[0]?.ProductId ?? "";
            }
            return "";
        }
        
        private static string TryGetCurrentProductId()
        {
            if (GuruIAP.Instance != null && IsIAPReady)
            {
                return GuruIAP.Instance.CurrentBuyingProductId;
            }
            return "";
        }
        
        
        /// 
        /// 当付费页面打开时调用 (iap_imp)
        /// 
        /// 付费页场景名称
        /// 
        public static void LogIAPImp(string scene, Dictionary extra = null)
        {
            Analytics.IAPImp(scene, extra);
        }
        /// 
        /// 当付费页面关闭时调用 (iap_close)
        /// 
        /// 
        /// 
        public static void LogIAPClose(string scene, Dictionary extra = null)
        {
            Analytics.IAPClose(scene, extra);
        }
        /// 
        /// 当点击 IAP 商品按钮的时候调用 (iap_clk)
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void LogIAPClick(string scene, string productId, string basePlan = "", string offerId = "", Dictionary extra = null)
        {
            Analytics.IAPClick(scene, productId, basePlan, offerId, extra);
        }
        
        #endregion
        #region 经济打点
        
        // ************************************************************************************************
        // *
        // *                                        经济打点
        // * 内容详参: https://docs.google.com/spreadsheets/d/1xYSsAjbrwqeJm7panoVzHO0PeGRQVDCR4e2CU9OPEzk/edit#gid=0
        // *
        // ************************************************************************************************
        
        //---------------------------------------- EARN ---------------------------------------- 
        /// 
        /// 基础收入接口 (earn_virtual_currency)
        /// 可直接调用此接口上报相关参数
        /// 获取虚拟货币/道具. 
        /// 基础接口, 不推荐项目组直接调用
        /// 请直接调用其他对应场景的统计接口
        /// 
        /// 货币名称
        /// 货币增加值 10
        /// 结算后货币总量 20 -> 30
        /// 消耗类型, 默认值请赋 reward
        /// 当前关卡或者人物等级名称
        /// 购买道具名称
        /// 购买场景如 Store, Workbench, Sign, Ads....
        /// 自定义数据
        public static void LogEarnVirtualCurrency(string currencyName, 
            int value, int balance, 
            string category = "", string itemName = "",
            string levelName = "", string scene = "", Dictionary extra = null)
        {
            Analytics.EarnVirtualCurrency(currencyName, value, balance, category, itemName,levelName, scene, extra);
        }
        
        /// 
        /// 游戏初次启动/用户获得初始道具
        /// 
        /// 货币名称
        /// 货币增加值 10
        /// 结算后货币总量 20 -> 30
        /// 购入道具 ID / 道具名称
        /// 购买场景如 Store, Workbench, Sign, Ads....
        /// 自定义数据
        public static void LogEarnVirtualCurrencyByFirstOpen(string currencyName, 
            int value, int balance, 
            string levelName = "", string scene = "", Dictionary extra = null)
        {
            string item_category = Consts.CurrencyCategoryReward;
            string item_name = "first_open";
            Analytics.EarnVirtualCurrency(currencyName, value, balance, item_category, item_name,levelName, scene, extra);
        }
        /// 
        /// 出售道具后获取货币
        /// 
        /// 货币名称
        /// 货币增加值 10
        /// 结算后货币总量 20 -> 30
        /// 购买道具名称
        /// 当前关卡或者人物等级名称
        /// 购买场景如 Store, Workbench, Sign, Ads....
        /// 自定义数据
        public static void LogEarnVirtualCurrencyBySellItem(string currencyName, 
            int value, int balance, string itemName,
            string levelName = "", string scene = "", Dictionary extra = null)
        {
            string item_category = Consts.CurrencyCategoryIGC;
            Analytics.EarnVirtualCurrency(currencyName, value, balance, item_category, itemName,levelName, scene, extra);
        }
        
        
        /// 
        /// 赚取组合: 货币+道具 (earn_virtual_currency) (props)
        /// 
        /// 货币名称
        /// 货币增加值 10
        /// 结算后货币总量 20 -> 30
        /// 消耗类型, 默认值请赋 reward
        /// 购买道具名称
        /// 获取的道具组合
        /// 当前关卡或者人物等级名称
        /// 购买场景如 Store, Workbench, Sign, Ads....
        /// 自定义数据
        private static void LogEarnVirtualCurrencyAndProps(string currencyName, 
            int value = 0, int balance = 0,
            string category = "", string itemName = "",
            string levelName = "", string scene = Consts.ParameterDefaultScene,  
            string[] props = null, Dictionary extra = null)
        {
            //---- Currency -----
            if (value > 0)
            {
                LogEarnVirtualCurrency(currencyName, value, balance, category, itemName, levelName, scene, extra);
            }
            //---- Props --------
            if (null != props)
            {
                int i = 0;
                while (i < props.Length)
                {
                    LogEarnVirtualCurrency(props[i], 1, 0, category, itemName, levelName, scene, extra);
                    i++;
                }
            }
        }
        /// 
        /// 签到奖励. 获得货币/道具 (earn_virtual_currency) (reward:sign)
        /// 通常类型: Coin 收入 
        /// 特殊类型: Coin + Props (道具列表) 
        /// 特殊类型: Props (道具列表) 
        /// 
        /// 货币名称
        /// 赚取金额
        /// 货币总量(累加后)
        /// 当前关卡名称
        /// 应用场景
        /// 获取的道具名称列表
        /// 
        public static void LogEarnVirtualCurrencyBySign(string currencyName, 
            int value = 0, int balance = 0, string levelName = "", 
            string scene = "home_page", string[] props = null, Dictionary extra = null)
        {
            string category = Consts.CurrencyCategoryReward;
            string itemName = "sign";
            LogEarnVirtualCurrencyAndProps(currencyName, value, balance, category, itemName, levelName, scene, props, extra);
        }
        /// 
        /// IAP 付费购买. 获得货币/道具 (earn_virtual_currency) (iap_buy:sku)
        /// 通常类型: Coin 收入 
        /// 特殊类型: Coin + Props (道具列表) 
        /// 特殊类型: Props (道具列表)  
        /// 
        /// IAP 道具名称
        /// 赚取金额
        /// 货币总量(累加后)
        /// 当前关卡名称
        /// 应用场景
        /// 获取的道具名称列表
        /// 
        public static void LogEarnVirtualCurrencyByIAP(string currencyName,
            int value = 0, int balance = 0, string levelName = "", 
            string scene = "store", string[] props = null, Dictionary extra = null)
        {
            string category = Consts.CurrencyCategoryIAP;
            // string itemName = productId;
            string itemName = "sku";
            LogEarnVirtualCurrencyAndProps(currencyName, value, balance, category, itemName, levelName, scene, props, extra);
        }
        /// 
        /// 看广告获取到货币/道具 (earn_virtual_currency) (reward:ads)
        /// 通常类型: Coin 收入 
        /// 特殊类型: Coin + Props (道具列表) 
        /// 特殊类型: Props (道具列表)  
        /// 
        /// 货币名称
        /// 赚取金额
        /// 货币总量(累加后)
        /// 当前关卡名称
        /// 应用场景
        /// 获取的道具名称列表
        /// 
        public static void LogEarnVirtualCurrencyByAds(string currencyName, 
            int value = 0, int balance = 0, string levelName = "", 
            string scene = "store", string[] props = null, Dictionary extra = null)
        {
            string category = Consts.CurrencyCategoryReward;
            string itemName = "ads";
            LogEarnVirtualCurrencyAndProps(currencyName, value, balance, category, itemName, levelName, scene, props, extra);
        }
        /// 
        /// 使用了金币半价 + 看广告获取到货币/道具 (earn_virtual_currency) (bonus:ads)
        /// 通常类型: Coin 收入 
        /// 特殊类型: Coin + Props (道具列表) 
        /// 特殊类型: Props (道具列表)  
        /// 
        /// 货币名称
        /// 赚取金额
        /// 货币总量(累加后)
        /// 当前关卡名称
        /// 应用场景
        /// 获取的道具名称列表
        /// 
        public static void LogEarnVirtualCurrencyByPaidAds(string currencyName, 
            int value = 0, int balance = 0, string levelName = "", 
            string scene = Consts.ParameterDefaultScene, string[] props = null, Dictionary extra = null)
        {
            string category = Consts.CurrencyCategoryBonus;
            string itemName = "ads";
            LogEarnVirtualCurrencyAndProps(currencyName, value, balance, category, itemName, levelName, scene, props, extra);
        }
        /// 
        /// 过关奖励获取到货币/道具 (earn_virtual_currency) (reward:level) 
        /// 通常类型: Coin 收入 
        /// 特殊类型: Coin + Props (道具列表) 
        /// 特殊类型: Props (道具列表)  
        /// 
        /// 货币名称
        /// 赚取金额
        /// 货币总量(累加后)
        /// 当前关卡名称
        /// 应用场景
        /// 获取的道具名称列表
        /// 
        public static void LogEarnVirtualCurrencyByLevelComplete(string currencyName, 
            int value = 0, int balance = 0, string levelName = "", 
            string scene = "store", string[] props = null, Dictionary extra = null)
        {
            string category = Consts.CurrencyCategoryReward;
            string itemName = "level";
            LogEarnVirtualCurrencyAndProps(currencyName, value, balance, category, itemName, levelName, scene, props, extra);
        }
        /// 
        /// 购买获得 Prop (earn_virtual_currency) (reward:level) 
        /// 记录 Prop 增加的打点, 消费游戏内货币
        /// 
        /// 购买的道具名称
        /// 消费货币名称
        /// 应用场景
        /// 购入数量
        /// 道具总量(累加后)
        /// 当前关卡名称
        /// 
        public static void LogEarnVirtualCurrencyByIGC(string currencyName, string spendCurrencyName, int value = 0, int balance = 0, 
            string levelName = "", string scene = "", Dictionary extra = null)
        {
            string category = Consts.CurrencyCategoryIGC;
            string itemName = spendCurrencyName;
            if (string.IsNullOrEmpty(scene)) scene = Consts.ParameterDefaultScene;
            LogEarnVirtualCurrencyAndProps(currencyName, value, balance, category, itemName, levelName, scene, null, extra); // TODO 这里的打点不对
        }
        /// 
        /// 通过道具交换/合成或得了其他道具 (earn_virtual_currency) (igb:coin) 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void LogEarnPropByProp(string propName, string otherName,
            string scene = Consts.ParameterDefaultScene,
            int value = 1, int balance = 0, string levelName = "", Dictionary extra = null)
        {
            string category = Consts.CurrencyCategoryIGB;
            LogEarnVirtualCurrency(propName, value, balance, category, otherName, levelName, scene, extra);
        }
        /// 
        /// 通过转盘或者抽奖, 获取货币/道具 (earn_virtual_currency) (igb:lottery) 
        /// 通常类型: Coin 收入 
        /// 特殊类型: Coin + Props (道具列表) 
        /// 特殊类型: Props (道具列表)  
        /// 
        /// 货币名称
        /// 赚取金额
        /// 货币总量(累加后)
        /// 当前关卡名称
        /// 应用场景
        /// 获取的道具名称列表
        /// 
        public static void LogEarnVirtualCurrencyByLottery(string currencyName, 
            int value = 0, int balance = 0, string levelName = "", 
            string scene = "store", string[] props = null, Dictionary extra = null)
        {
            string category = Consts.CurrencyCategoryIGB;
            string itemName = "lottery";
            LogEarnVirtualCurrencyAndProps(currencyName, value, balance, category, itemName, levelName, scene, props, extra);
        }
        
        
        //---------------------------------------- SPEND ---------------------------------------- 
        /// 
        /// 基础花费虚拟货币/道具 (spend_virtual_currency)
        /// 基础接口, 不推荐项目组直接调用
        /// 请直接调用其他对应场景的统计接口
        /// 
        /// 货币名称
        /// 货币消耗值 10
        /// 结算后货币总量 30 -> 20
        /// 消耗类型, 默认值请赋 reward
        /// 当前关卡或者人物等级名称
        /// 购买道具名称
        /// 购买场景如 Store, Workbench, Sign, Ads....
        /// 
        public static void LogSpendVirtualCurrency(string currencyName, int value, int balance, string category = "", string itemName = "",
            string levelName = "", string scene = "", Dictionary extra = null)
        {
            Analytics.SpendVirtualCurrency(currencyName, value, balance, category, itemName, levelName, scene, extra);
        }
        
        /// 
        /// 消耗 Boost 道具
        /// 
        /// 货币/道具名称
        /// 货币消耗值 10
        /// 结算后货币总量 30 -> 20
        /// 
        /// 
        /// 
        /// 
        public static void LogSpendVirtualCurrencyAsBoost(string currencyName, int value, int balance, string itemName = "",
            string levelName = "", string scene = "", Dictionary extra = null)
        {
            string category = Consts.CurrencyCategoryBoost;
            Analytics.SpendVirtualCurrency(currencyName, value, balance, category, itemName, levelName, scene, extra);
        }
        
        /// 
        /// 消耗货币购买道具 (spend_virtual_currency) (props)
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void LogSpendVirtualCurrencyWithProp(string currencyName, string prop,
            int value, int balance,
            string levelName = "", string scene = "", Dictionary extra = null)
        {
            string category = Consts.CurrencyCategoryProp;
            LogSpendVirtualCurrency(currencyName, value, balance, category, prop, levelName, scene, extra); 
        }
        /// 
        /// 消耗货币购买道具 (含多个) (spend_virtual_currency) (props)
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void LogSpendVirtualCurrencyWithProps(string currencyName, string[] props,
            int value, int balance, 
            string levelName = "", string scene = "", Dictionary extra = null)
        {
            string category = Consts.CurrencyCategoryProps;
            if (props != null && props.Length > 0)
            {
                int i = 0;
                while (i < props.Length)
                {
                    LogSpendVirtualCurrency(currencyName, value, balance, category, props[i], levelName, scene, extra); 
                    i++;
                }
            }
        }
        /// 
        /// 消耗货币购买礼包或组合 (spend_virtual_currency) (bundle)
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void LogSpendVirtualCurrencyWithBundle(string currencyName, string bundle,
            int value, int balance,
            string levelName = "", string scene = "", Dictionary extra = null)
        {
            LogSpendVirtualCurrencyWithBundles(currencyName, new string[] {bundle}, value, balance, levelName, scene, extra);
        }
        /// 
        /// 消耗货币购买礼包或组合 (复数) (spend_virtual_currency) (bundle)
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void LogSpendVirtualCurrencyWithBundles(string currencyName, string[] bundles,
            int value, int balance, 
            string levelName = "", string scene = "", Dictionary extra = null)
        {
            string category = Consts.CurrencyCategoryBundle;
            if (bundles != null && bundles.Length > 0)
            {
                int i = 0;
                while (i < bundles.Length)
                {
                    LogSpendVirtualCurrency(currencyName, value, balance, category, bundles[i], levelName, scene, extra); 
                    i++;
                }
            }
        }
        /// 
        /// 消耗物品, 交换其他物品 (spend_virtual_currency) (prop)
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void LogSpendPropWithProp(string propName, string otherName,
            int value, int balance, 
            string levelName = "", string scene = "", string extraCategory = "", Dictionary extra = null)
        {
            string category = string.IsNullOrEmpty(extraCategory) ? Consts.CurrencyCategoryProp : extraCategory;
            LogSpendVirtualCurrency(propName, value, balance, category, otherName, levelName, scene, extra); 
        }
        #endregion
        #region ATT 二次引导弹窗
        
        /// 
        /// ATT 二次引导弹窗展示 (att_reguide_imp)
        /// 
        /// 引导样式名称
        /// 第几次展示
        /// 举例安装日期的天数
        /// 扩展数据
        public static void LogAttReguideImp(string type, 
            int showTimes = 1, int installDays = 0, Dictionary extra = null)
        {
            var dict = new Dictionary()
            {
                ["type"] = type,
                ["show_times"] = showTimes,
                ["install_days"] = installDays,
            };
            if (extra != null) dict = GuruSDKUtils.MergeDictionary(dict, extra);
            LogEvent(Consts.EventAttReguideImp, dict);
        }
        
        /// 
        /// ATT 二次引导弹窗点击 (att_reguide_clk)
        /// 
        /// 引导样式名称
        /// 第几次展示
        /// 举例安装日期的天数
        /// 点击引导页的动作:dissmiss/go
        /// 扩展数据
        public static void LogAttReguideClick(string type, string action, 
            int showTimes = 1, int installDays = 0, Dictionary extra = null)
        {
            var dict = new Dictionary()
            {
                ["type"] = type,
                ["show_times"] = showTimes,
                ["install_days"] = installDays,
                ["action"] = action,
            };
            if (extra != null) dict = GuruSDKUtils.MergeDictionary(dict, extra);
            LogEvent(Consts.EventAttReguideClk, dict);
        }
        /// 
        /// ATT 二次引导弹窗展示结果 (att_reguide_result)
        /// 
        /// 引导样式名称
        /// 第几次展示
        /// 举例安装日期的天数
        /// 点击引导页的动作:dissmiss/go
        /// 结果字段:authorized, denied, restricted, notDetermined
        /// 扩展数据
        public static void LogAttReguideResult(string type, string action, string result, 
            int showTimes = 1, int installDays = 0, Dictionary extra = null)
        {
            var dict = new Dictionary()
            {
                ["type"] = type,
                ["show_times"] = showTimes,
                ["install_days"] = installDays,
                ["action"] = action,
                [Consts.ParameterItemCategory] = result,
            };
            if (extra != null) dict = GuruSDKUtils.MergeDictionary(dict, extra);
            LogEvent(Consts.EventAttReguideResult, dict);
        }
        
        #endregion
        
        #region 教程引导
        
        /// 
        /// 教程开始
        /// 
        /// 扩展数据
        public static void LogTutorialBegin(Dictionary extra = null)
        {
            LogEvent(Consts.EventTutorialBegin, extra);
        }
        /// 
        /// 教程开始
        /// 
        /// 教程步骤
        /// 扩展数据
        public static void LogTutorialImp(int step, Dictionary extra = null)
        {
            string key = Consts.EventTutorialImp.Replace("{0}", step.ToString());
            LogEvent(key, extra);
        }
        /// 
        /// 教程开始
        /// 
        /// 教程步骤
        /// 扩展数据
        public static void LogTutorialNextClick(int step, Dictionary extra = null)
        {
            string key = Consts.EventTutorialNextClick.Replace("{0}", step.ToString());
            LogEvent(key, extra);
        }
        /// 
        /// 教程结束
        /// 
        /// 扩展数据
        public static void LogTutorialComplete(Dictionary extra = null)
        {
            LogEvent(Consts.EventTutorialComplete, extra);
        }
        /// 
        /// 教程页面关闭
        /// 
        /// 扩展数据
        public static void LogTutorialClose(Dictionary extra = null)
        {
            LogEvent(Consts.EventTutorialClose, extra);
        }
        #endregion
        #region 消息权限弹窗打点
        /// 
        /// 通知栏请求权限展示时触发 (noti_perm_imp)
        /// 
        /// 弹窗样式
        /// 请求弹窗的次数
        /// 展现弹窗的次数
        /// 点击 deny 的次数
        /// 弹窗触发来源
        /// 弹窗场景
        /// 扩展参数
        public static void LogNotiPermImp(int requestTimes,  int showTimes, int deniedTimes, string promptTrigger,string style = "default",  string scene = "", Dictionary extra = null)
        {
            var dict = new Dictionary()
            {
                [Consts.ParameterItemCategory] = style,
                ["request_times"] = requestTimes,
                ["show_times"] = showTimes,
                ["denied_times"] = deniedTimes,
                ["prompt_trigger"] = promptTrigger,
            };
            if (!string.IsNullOrEmpty(scene))
                dict[Consts.ParameterItemName] = scene;
            if (extra != null) dict = GuruSDKUtils.MergeDictionary(dict, extra);
            LogEvent(Consts.EventNotiPermImp, dict);
        }
        
        /// 
        /// 得到权限结果时触发 (noti_perm_result)
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void LogNotiPermResult( int requestTimes,  int showTimes, int deniedTimes, string result, string promptTrigger, string style = "default", string scene = "", Dictionary extra = null)
        {
            var dict = new Dictionary()
            {
                ["request_times"] = requestTimes,
                ["show_times"] = showTimes,
                ["denied_times"] = deniedTimes,
                ["prompt_trigger"] = promptTrigger,
                ["result"] = result,
                [Consts.ParameterItemCategory] = style,
            };
            if (!string.IsNullOrEmpty(scene))
                dict[Consts.ParameterItemName] = scene;
            if (extra != null) dict = GuruSDKUtils.MergeDictionary(dict, extra);
            LogEvent(Consts.EventNotiPermResult, dict);
        }
        
        /// 
        /// 说明性通知栏权限引导展示时触发 (noti_perm_rationale_imp)
        /// 
        /// 引导页的名称,自定义
        /// 
        /// 
        public static void LogNotiPermRationaleImp(string pageName, string scene = "", Dictionary extra = null)
        {
            var dict = new Dictionary()
            {
                [Consts.ParameterItemCategory] = pageName,
            };
            if (!string.IsNullOrEmpty(scene))
                dict[Consts.ParameterItemName] = scene;
            if (extra != null) dict = GuruSDKUtils.MergeDictionary(dict, extra);
            LogEvent(Consts.EventNotiPermRationaleImp, dict);
        }
        
        /// 
        /// 说明性通知栏权限引导结果时触发 (noti_perm_rationale_result)
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void LogNotiPermRationaleResult(string result, string pageName, string scene = "", Dictionary extra = null)
        {
            var dict = new Dictionary()
            {
                ["result"] = result,
                [Consts.ParameterItemCategory] = pageName,
            };
            if (!string.IsNullOrEmpty(scene))
                dict[Consts.ParameterItemName] = scene;
            if (extra != null) dict = GuruSDKUtils.MergeDictionary(dict, extra);
            LogEvent(Consts.EventNotiPermRationaleResult, dict);
        }
        #endregion
        #region 错误时间上报
        /// 
        /// 上报错误事件
        /// 
        /// 
        /// 
        /// 
        /// 
        public static void LogDevAudit(string errorCode, string err, string country = "", string network = "")
        {
            var dict = new Dictionary()
            {
                [Consts.ParameterItemCategory] = "error_event",
                [Consts.ParameterItemName] = errorCode,
                ["err"] = err,
                ["country"] = country,
                ["network"] = network,
            };
            LogEvent(Consts.EventDevAudit, dict);
        }
        #endregion
        
        #region Crashlytics 接口
        public static void CrashLog(string message)
        {
            if (!IsFirebaseReady) return;
            CrashlyticsAgent.Log(message);
        }
        
        public static void CrashException(string message)
        {
            if (!IsFirebaseReady) return;
            CrashlyticsAgent.LogException(message);
        }
        public static void CrashException(Exception ex)
        {
            if (!IsFirebaseReady) return;
            CrashlyticsAgent.LogException(ex);
        }
        public static void CrashCustomKeys(string key, string value)
        {
            if (!IsFirebaseReady) return;
            CrashlyticsAgent.SetCustomKey(key, value);
        }
        #endregion
        #region 优先级设置
        
        
        /// 
        /// 设置
        /// 
        /// 
        /// 
        public static void SetEventPriority(EventPriority priority, string[] eventNames)
        {
            if (Model.event_priorities == null) Model.event_priorities = new Dictionary(10);
            int i = 0;
            while (i < eventNames.Length)
            {
                var evt = eventNames[i];
                if (!string.IsNullOrEmpty(evt))
                {
                    Model.event_priorities[evt] = (int)priority;
                }
                i++;
            }
        }
        public static void SetEventPriority(EventPriority priority, string eventName)
        {
            SetEventPriority(priority, new string[]{eventName});
        }
        public static EventPriority GetEventPriority(string eventName)
        {
            if (Model.event_priorities != null 
                && Model.event_priorities.TryGetValue(eventName, out int p))
            {
                return (EventPriority)p;
            }
            return EventPriority.Default;
        }
        
        internal static int GetEventPriorityInt(string eventName)
        {
            return (int)GetEventPriority(eventName);
        }
        /// 
        /// set all events as 'Emergence' event, which will be triggered immediately
        /// 
        internal void SetSDKEventPriority()
        {
            SetEventPriority(EventPriority.Emergence, new []
            {
                Consts.EventTchAdRev001Impression,
                Consts.EventTchAdRev02Impression,
                Consts.EventLevelStart,
                Consts.EventLevelEnd,
            });
        }
        #endregion
    }
}