namespace Guru
{
	using System;
    using UnityEngine;
    using Firebase.Analytics;
    using System.Collections.Generic;

	/// <summary>
	/// 上报用户属性逻辑
	/// Firebase 中台属性上报： https://docs.google.com/spreadsheets/d/1N47rXgjatRHFvzWWx0Hqv5C1D9NHHGbggi6pQ65c-zQ/edit?gid=1858695240#gid=1858695240
	/// Guru自打点 中台属性上报：https://docs.google.com/spreadsheets/d/1N47rXgjatRHFvzWWx0Hqv5C1D9NHHGbggi6pQ65c-zQ/edit?gid=1736574940#gid=1736574940
	/// </summary>
    public static partial class Analytics
    {
        
        
        #region Old Properties
        
        /// <summary>
        /// B_Level 属性
        /// </summary>
        public static int BLevel
        {
            get => PlayerPrefs.GetInt(nameof(BLevel), 0);
            set => PlayerPrefs.SetInt(nameof(BLevel), value);
        }
        /// <summary>
        /// B_Play 属性
        /// </summary>
        public static int BPlay
        {
            get => PlayerPrefs.GetInt(nameof(BPlay), 0);
            set => PlayerPrefs.SetInt(nameof(BPlay), value);
        }

        #endregion

        #region Update all neccessary properties
        
        //---------------- 设置所有必要的属性 ---------------------
		
        /// <summary>
        /// 应用所有的中台属性
        /// </summary>
        private static void ApplyAllMidWareProperties()
        {
	        MidWarePropertiesManager.Instance.ApplyAllProperties();
        }


        /// <summary>
		/// 设置用户ID
		/// </summary>
		public static void SetUid(string uid)
		{
			MidWarePropertiesManager.Instance.ReportUid(uid);
		}
        
		/// <summary>
		/// 设置用户ID
		/// </summary>
		public static void SetBLevel(int bLevel)
		{
			MidWarePropertiesManager.Instance.ReportBLevel($"{bLevel}");
		}
		
		/// <summary>
		/// 设置用户ID
		/// </summary>
		public static void SetBPlay(int bPlay)
		{
			MidWarePropertiesManager.Instance.ReportBPlay($"{bPlay}");
		}

		/// <summary>
		/// 设置Analytics 实验分组
		/// (Firebase, Guru)
		/// </summary>
		private static void SetAnalyticsExperimentGroup(string groupName)
		{
			MidWarePropertiesManager.Instance.ReportAnalyticsExperimentGroup(groupName);
		}
		
		/// <summary>
		/// 设置账号登录方法
		/// (Firebase, Guru)
		/// </summary>
		internal static void SetSignUpMethod(string methodName)
		{
			MidWarePropertiesManager.Instance.ReportSignUpMethod(methodName);
		}
        
		/// <summary>
		/// 设置设备ID
		/// (Firebase, Guru)
		/// </summary>
		private static void SetDeviceId(string deviceId)
		{
			MidWarePropertiesManager.Instance.ReportDeviceId(deviceId);
		}
		
		/// <summary>
		/// 设置首次启动时间
		/// </summary>
		/// <param name="firstOpenTime"></param>
		private static void SetFirstOpenTime(string firstOpenTime)
		{
			MidWarePropertiesManager.Instance.ReportFirstOpenTime(firstOpenTime);
		}
		
		/// <summary>
		/// 设置 IsIapUser
		/// (Firebase, Guru)
		/// </summary>
		public static void SetIsIapUser(bool isIapUser)
		{
			MidWarePropertiesManager.Instance.ReportIsIapUser(isIapUser);
		}
		
		/// <summary>
		/// 设置 Network
		/// (Firebase, Guru)
		/// </summary>
		public static void SetNetworkStatus(string networkStatus)
		{
			MidWarePropertiesManager.Instance.ReportNetworkStatus(networkStatus);
		}

		/// <summary>
		/// 设置 AdjustId
		/// (Firebase)
		/// </summary>
		public static void SetAdjustId(string adjustId)
		{
			MidWarePropertiesManager.Instance.ReportAdjustId(adjustId);
		}
		
		/// <summary>
		/// 设置 AndroidId
		/// (Firebase)
		/// </summary>
		public static void SetAndroidId(string androidId)
		{
			MidWarePropertiesManager.Instance.ReportAndroidId(androidId);
		}
		
		/// <summary>
		/// 设置 AttStatus
		/// (Firebase)
		/// </summary>
		public static void SetAttStatus(string attStatus)
		{
			MidWarePropertiesManager.Instance.ReportAttStatus(attStatus);
		}
		
		/// <summary>
		/// 设置 AttStatus
		/// (Firebase)
		/// </summary>
		public static void SetNotiPerm(string notiPrem)
		{
			MidWarePropertiesManager.Instance.ReportNotiPerm(notiPrem);
		}
		
		/// <summary>
		/// 设置 AdId
		/// </summary>
		public static void SetGoogleAdId(string adId)
		{
			MidWarePropertiesManager.Instance.ReportGoogleAdId(adId);
		}

		public static void SetIDFV(string idfv)
		{
			MidWarePropertiesManager.Instance.ReportIDFV(idfv);
		}

		public static void SetIDFA(string idfa)
		{
			MidWarePropertiesManager.Instance.ReportIDFA(idfa);
		}
		

        #endregion
        
        #region 中台属性管理

        /// <summary>
        /// 中台必要用户属性对象
        /// </summary>
        private abstract class AbstractMidWareProperty
        {
	        public readonly string key;
	        protected readonly string value;
	        private readonly  ReportPropertyTarget reportTarget;
	        private bool HasValue => !string.IsNullOrEmpty(value);

	        protected AbstractMidWareProperty(string key, string value,
		        ReportPropertyTarget reportTarget = ReportPropertyTarget.Both)
	        {
		        this.key = key;
		        this.value = value;
		        this.reportTarget = reportTarget;
	        }


	        public void Report()
	        {
		        if (!HasValue) return;
		        BeforeReportProperty();
		        ReportPropertyByTarget();
	        }

	        protected abstract void BeforeReportProperty();

	        private void ReportPropertyByTarget()
	        {
		        if (!HasValue) return;
		        switch (reportTarget)
		        {
			        case ReportPropertyTarget.Firebase:
				        // Firebase
				        _firebaseEventDriver.AddProperty(key, value);
				        break;
			        
			        case ReportPropertyTarget.Guru:
				        // Guru
				        _guruEventDriver.AddProperty(key, value);
				        break;
			        
			        case ReportPropertyTarget.Both:
				        // 双平台上报
				        _firebaseEventDriver.AddProperty(key, value);
				        _guruEventDriver.AddProperty(key, value);
				        break;
			        
			        default:
				        throw new ArgumentOutOfRangeException();
		        }
	        }

        }

		/// <summary>
		/// UID
		/// </summary>
        private class MidWarePropertyUid : AbstractMidWareProperty
        {
	        public MidWarePropertyUid(string value) 
		        : base(PropertyUserID, value, ReportPropertyTarget.Both)
	        {
	        }
	        
	        protected override void BeforeReportProperty()
	        {
				_firebaseEventDriver.SetUid(value);
		        _guruEventDriver.SetUid(value);
	        }
        }
        /// <summary>
        /// BLevel
        /// </summary>
        private class MidWarePropertyBLevel : AbstractMidWareProperty
        {
	        public MidWarePropertyBLevel(string value) 
		        : base(PropertyLevel, value, ReportPropertyTarget.Both)
	        {
	        }
	        
	        protected override void BeforeReportProperty()
	        {
	        }
        }
        /// <summary>
        /// BLevel
        /// </summary>
        private class MidWarePropertyBPlay : AbstractMidWareProperty
        {
	        public MidWarePropertyBPlay(string value) 
		        : base(PropertyPlay, value, ReportPropertyTarget.Both)
	        {
	        }
	        
	        protected override void BeforeReportProperty()
	        {
	        }
        }
		
		
        /// <summary>
        /// SignUpMethod
        /// </summary>
        private class MidWarePropertySignUpMethod : AbstractMidWareProperty
        {
	        public MidWarePropertySignUpMethod(string value) 
		        : base(PropertySignUpMethod, value, ReportPropertyTarget.Both)
	        {
		        
	        }
	        protected override void BeforeReportProperty()
	        {
	        }
        }
        /// <summary>
        /// AnalyticsExperimentGroup
        /// </summary>
        private class MidWarePropertyAnalyticsExperimentGroup : AbstractMidWareProperty
        {
	        public MidWarePropertyAnalyticsExperimentGroup(string value) 
		        : base(PropertyAnalyticsExperimentalGroup, value, ReportPropertyTarget.Both)
	        {
		        
	        }
	        protected override void BeforeReportProperty()
	        {
	        }
        }
        /// <summary>
        /// DeviceId
        /// </summary>
        private class MidWarePropertyDeviceId : AbstractMidWareProperty
        {
	        public MidWarePropertyDeviceId(string value) 
		        : base(PropertyDeviceID, value, ReportPropertyTarget.Both)
	        {
		        
	        }
	        
	        protected override void BeforeReportProperty()
	        {
		        _guruEventDriver.SetDeviceId(value);
	        }
        }
        /// <summary>
        /// FirstOpenTime
        /// </summary>
        private class MidWarePropertyFirstOpenTime : AbstractMidWareProperty
        {
	        public MidWarePropertyFirstOpenTime(string value) 
		        : base(PropertyFirstOpenTime, value, ReportPropertyTarget.Both)
	        {
		        
	        }

	        protected override void BeforeReportProperty()
	        {
	        }
        }
        /// <summary>
        /// IsIapUser
        /// </summary>
        private class MidWarePropertyIsIapUser : AbstractMidWareProperty
        {
	        public MidWarePropertyIsIapUser(bool value) 
		        : base(PropertyIsIAPUser, value?"true":"false", ReportPropertyTarget.Both)
	        {
		        
	        }
	        
	        protected override void BeforeReportProperty() { }
        }
        
        /// <summary>
        /// Network
        /// </summary>
        private class MidWarePropertyNetwork : AbstractMidWareProperty
        {
	        public MidWarePropertyNetwork(string value) 
		        : base(PropertyNetwork, value, ReportPropertyTarget.Both)
	        {
		        
	        }
	        
	        protected override void BeforeReportProperty() { }
        }
        /// <summary>
        /// AdjustId
        /// </summary>
        private class MidWarePropertyAdjustId : AbstractMidWareProperty
        {
	        public MidWarePropertyAdjustId(string value) 
		        : base(PropertyAdjustId, value, ReportPropertyTarget.Firebase)
	        {
		        
	        }

	        protected override void BeforeReportProperty()
	        {
		        _guruEventDriver.SetAdjustId(value);
	        }
        }
        
        /// <summary>
        /// AttStatus
        /// </summary>
        private class MidWarePropertyAttStatus : AbstractMidWareProperty
        {
	        public MidWarePropertyAttStatus(string value) 
		        : base(PropertyAttStatus, value, ReportPropertyTarget.Both)
	        {
		        
	        }

	        protected override void BeforeReportProperty()
	        {
		        
	        }
        }
        
        /// <summary>
        /// AttStatus
        /// </summary>
        private class MidWarePropertyNotiPerm : AbstractMidWareProperty
        {
	        public MidWarePropertyNotiPerm(string value) 
		        : base(PropertyNotiPerm, value, ReportPropertyTarget.Both)
	        {
		        
	        }

	        protected override void BeforeReportProperty()
	        {
		        
	        }
        }

        
        /// <summary>
        /// AndroidId
        /// </summary>
        private class MidWarePropertyAndroidId : AbstractMidWareProperty
        {
	        public MidWarePropertyAndroidId(string value) 
		        : base(PropertyAndroidId, value, ReportPropertyTarget.Both)
	        {
	        }
	        
	        protected override void BeforeReportProperty()
	        {
		        _guruEventDriver.SetAndroidId(value);
	        }
        }
        
        /// <summary>
        /// FirebaseId
        /// </summary>
        private class MidWarePropertyGoogleAdId : AbstractMidWareProperty
        {
	        public MidWarePropertyGoogleAdId(string value) 
		        : base(PropertyGoogleAdId, value, ReportPropertyTarget.Both)
	        {
	        }
	        
	        protected override void BeforeReportProperty()
	        {
		        _guruEventDriver.SetGoogleAdId(value);
	        }
        }
        
        /// <summary>
        /// IDFV
        /// </summary>
        private class MidWarePropertyIDFV : AbstractMidWareProperty
        {
	        public MidWarePropertyIDFV(string value) 
		        : base(PropertyIDFV, value, ReportPropertyTarget.Both)
	        {
	        }
	        
	        protected override void BeforeReportProperty()
	        {
		        _guruEventDriver.SetIDFV(value);
	        }
        }
        
        /// <summary>
        /// IDFV
        /// </summary>
        private class MidWarePropertyIDFA : AbstractMidWareProperty
        {
	        public MidWarePropertyIDFA(string value) 
		        : base(PropertyIDFA, value, ReportPropertyTarget.Both)
	        {
	        }
	        
	        protected override void BeforeReportProperty()
	        {
		        _guruEventDriver.SetIDFA(value);
	        }
        }
	
        /// <summary>
        /// 必要属性上报配置
        /// </summary>
        internal enum ReportPropertyTarget
        {
	        Firebase = 1,
	        Guru = 2,
	        Both = 3,
        }


        /// <summary>
        /// 全部属性集合
        /// </summary>
        internal class MidWarePropertiesManager
        {
	        
	        private static MidWarePropertiesManager _instance;

	        public static MidWarePropertiesManager Instance
	        {
		        get
		        {
			        if (_instance == null) _instance = new MidWarePropertiesManager();
			        return _instance;
		        }
	        }


	        private readonly Dictionary<string, AbstractMidWareProperty> _propertyMap = new Dictionary<string, AbstractMidWareProperty>(10);

	             
        /*
			=======  必打属性  ========
			user_id  (F,G)
			device_id (F,G)
			first_open_time (F,G)
			is_iap_user (F,G)
			network (F,G)

			adjust_id (F)
			att_status (F)
			noti_perm (F)
			=======  必打属性  ========
			
			=======  补充属性  ========
			firebase_id
			idfv
			idfa
			=======  补充属性  ========
		*/
	        
			//-------------------- 设置所有的属性 -----------------------
        
	        
	        public void ReportUid(string uid)
	        {
		        var prop = new MidWarePropertyUid(uid);
		        _propertyMap.TryAdd(prop.key, prop);
		        prop.Report();
	        }
	        public void ReportBLevel(string bLevel)
	        {
		        var prop = new MidWarePropertyBLevel(bLevel);
		        _propertyMap.TryAdd(prop.key, prop);
		        prop.Report();
	        }
	        public void ReportBPlay(string bPlay)
	        {
		        var prop = new MidWarePropertyBPlay(bPlay);
		        _propertyMap.TryAdd(prop.key, prop);
		        prop.Report();
	        }

	        public void ReportAnalyticsExperimentGroup(string groupName)
	        {
		        var prop = new MidWarePropertyAnalyticsExperimentGroup(groupName);
		        _propertyMap.TryAdd(prop.key, prop);
		        prop.Report();
	        }
	        
	        public void ReportSignUpMethod(string methodName)
	        {
		        var prop = new MidWarePropertySignUpMethod(methodName);
		        _propertyMap.TryAdd(prop.key, prop);
		        prop.Report();
	        }
	        
	        public void ReportDeviceId(string deviceId)
	        {
		        var prop = new MidWarePropertyDeviceId(deviceId);
		        _propertyMap.TryAdd(prop.key, prop);
		        prop.Report();
	        }
	        
	        public void ReportFirstOpenTime(string firstOpenTime)
	        {
		        var prop = new MidWarePropertyFirstOpenTime(firstOpenTime);
		        _propertyMap.TryAdd(prop.key, prop);
		        prop.Report();
	        }

	        public void ReportIsIapUser(bool isIapUser)
	        {
		        var prop = new MidWarePropertyIsIapUser(isIapUser);
		        _propertyMap.TryAdd(prop.key, prop);
		        prop.Report();
	        }
	        
	        public void ReportNetworkStatus(string networkStatus)
	        {
		        var prop = new MidWarePropertyNetwork(networkStatus);
		        _propertyMap.TryAdd(prop.key, prop);
		        prop.Report();
	        }
	        
	        public void ReportAdjustId(string adjustId)
	        {
		        var prop = new MidWarePropertyAdjustId(adjustId);
		        _propertyMap.TryAdd(prop.key, prop);
		        prop.Report();
	        }
	        
	        public void ReportAttStatus(string attStatus)
	        {
		        var prop = new MidWarePropertyAttStatus(attStatus);
		        _propertyMap.TryAdd(prop.key, prop);
		        prop.Report();
	        }
	        
	        public void ReportNotiPerm(string notiPerm)
	        {
		        var prop = new MidWarePropertyNotiPerm(notiPerm);
		        _propertyMap.TryAdd(prop.key, prop);
		        prop.Report();
	        }
	        
	        public void ReportAndroidId(string androidId)
	        {
		        var prop = new MidWarePropertyAndroidId(androidId);
		        _propertyMap.TryAdd(prop.key, prop);
		        prop.Report();
	        }
	        
	        public void ReportGoogleAdId(string googleAdId)
	        {
		        var prop = new MidWarePropertyGoogleAdId(googleAdId);
		        _propertyMap.TryAdd(prop.key, prop);
		        prop.Report();
	        }
	        
	        public void ReportIDFV(string idfv)
	        {
		        var prop = new MidWarePropertyIDFV(idfv);
		        _propertyMap.TryAdd(prop.key, prop);
		        prop.Report();
	        }
	        public void ReportIDFA(string idfa)
	        {
		        var prop = new MidWarePropertyIDFA(idfa);
		        _propertyMap.TryAdd(prop.key, prop);
		        prop.Report();
	        }

	        /// <summary>
	        /// 应用所有中台打点的用户属性
	        /// </summary>
	        public void ApplyAllProperties()
	        {
		        // 应用所有用户属性
		        Debug.Log($"{TAG} --- UpdateAllValues ---");

		        foreach (var prop in _propertyMap.Values)
		        {
			        prop.Report();
		        }
	        
		        ReportEventSuccessRate();
	        }
	        
	        /// <summary>
	        /// 上报事件成功率
	        /// </summary>
	        private static void ReportEventSuccessRate()
	        {
		        var interval = (DateTime.Now - _lastReportRateDate).TotalSeconds;
		        if (interval > _reportSuccessInterval)
		        {
			        GuruAnalytics.Instance.ReportEventSuccessRate();
			        _lastReportRateDate = DateTime.Now;
		        }
	        }
        }


        #endregion
    }

	
}