using System; 
 | 
using System.Collections; 
 | 
using System.Collections.Generic; 
 | 
using System.Linq; 
 | 
using UnityEngine; 
 | 
  
 | 
public class FirstChargeManager : GameSystemManager<FirstChargeManager> 
 | 
{ 
 | 
    public const int FuncID = 21; 
 | 
    public int mainItemId { get { return GetMainItemId(); } } 
 | 
    public int heroItemID; 
 | 
    public int maxGiftCount 
 | 
    { 
 | 
        get 
 | 
        { 
 | 
            var list = FirstChargeConfig.GetKeys(); 
 | 
            return list.IsNullOrEmpty() ? 0 : list.Count; 
 | 
        } 
 | 
    } 
 | 
    public int maxDay = 3; 
 | 
    public Redpoint parentRedpoint = new Redpoint(MainRedDot.FirstChargeRepoint); 
 | 
  
 | 
    public Dictionary<int, Redpoint> tabRedpointDict = new Dictionary<int, Redpoint>(); 
 | 
    public Dictionary<int, bool> clickTabDict = new Dictionary<int, bool>(); 
 | 
    public Dictionary<int, FirstChargeData> firstChargeInfoDict = new Dictionary<int, FirstChargeData>(); 
 | 
    public event Action OnUpdateFirstChargeInfo; 
 | 
    public override void Init() 
 | 
    { 
 | 
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent += OnBeforePlayerDataInitializeEvent; 
 | 
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent += OnPlayerLoginOk; 
 | 
        RechargeManager.Instance.rechargeCountEvent += OnRechargeCountEvent; 
 | 
        FuncOpen.Instance.OnFuncStateChangeEvent += OnFuncStateChangeEvent; 
 | 
        InitClickTabDict(); 
 | 
        InitRedPoint(); 
 | 
    } 
 | 
  
 | 
    public override void Release() 
 | 
    { 
 | 
        DTC0102_tagCDBPlayer.beforePlayerDataInitializeEvent -= OnBeforePlayerDataInitializeEvent; 
 | 
        DTC0403_tagPlayerLoginLoadOK.playerLoginOkEvent -= OnPlayerLoginOk; 
 | 
        RechargeManager.Instance.rechargeCountEvent -= OnRechargeCountEvent; 
 | 
        FuncOpen.Instance.OnFuncStateChangeEvent -= OnFuncStateChangeEvent; 
 | 
    } 
 | 
  
 | 
    private void OnFuncStateChangeEvent(int obj) 
 | 
    { 
 | 
        if (FuncID == obj) 
 | 
        { 
 | 
            string key = $"FirstCharge_FirstTime_{FuncID}_{PlayerDatas.Instance.baseData.PlayerID}"; 
 | 
            if (!LocalSave.HasKey(key)) 
 | 
            { 
 | 
                // 第一次开启功能 
 | 
                LocalSave.SetBool(key, true); 
 | 
                PopupWindowsProcessor.Instance.Add("FirstChargeWin"); 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    public void InitClickTabDict() 
 | 
    { 
 | 
        var list = FirstChargeConfig.GetKeys(); 
 | 
        if (!list.IsNullOrEmpty()) 
 | 
        { 
 | 
            for (int i = 0; i < list.Count; i++) 
 | 
            { 
 | 
                int firstId = list[i]; 
 | 
                clickTabDict[firstId] = false; 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
    public bool GetClickTabState(int fristId) 
 | 
    { 
 | 
        return clickTabDict.ContainsKey(fristId) && clickTabDict[fristId]; 
 | 
    } 
 | 
    public void SetClickTabState(int fristId) 
 | 
    { 
 | 
        clickTabDict[fristId] = true; 
 | 
        UpdateRedPoint(); 
 | 
    } 
 | 
  
 | 
    public void InitRedPoint() 
 | 
    { 
 | 
        var list = FirstChargeConfig.GetKeys(); 
 | 
        if (!list.IsNullOrEmpty()) 
 | 
        { 
 | 
            for (int i = 0; i < list.Count; i++) 
 | 
            { 
 | 
                int firstId = list[i]; 
 | 
                int redpointId = GetRedpointIdByFirstId(firstId); 
 | 
                tabRedpointDict[firstId] = new Redpoint(MainRedDot.FirstChargeRepoint, redpointId); 
 | 
            } 
 | 
        } 
 | 
  
 | 
    } 
 | 
  
 | 
    public int GetRedpointIdByFirstId(int firstId) 
 | 
    { 
 | 
        return MainRedDot.FirstChargeRepoint * 10000 + firstId; 
 | 
    } 
 | 
  
 | 
    private void OnRechargeCountEvent(int obj) 
 | 
    { 
 | 
        var list = FirstChargeConfig.GetCtgIDList(); 
 | 
        if (!list.IsNullOrEmpty() && list.Contains(obj)) 
 | 
        { 
 | 
            UpdateRedPoint(); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    public void OnBeforePlayerDataInitializeEvent() 
 | 
    { 
 | 
        firstChargeInfoDict.Clear(); 
 | 
    } 
 | 
  
 | 
    public void OnPlayerLoginOk() 
 | 
    { 
 | 
        if (FuncOpen.Instance.IsFuncOpen(FuncID) && TryGetUnBuyFirstId(out int firstId)) 
 | 
        { 
 | 
            PopupWindowsProcessor.Instance.Add("FirstChargeWin"); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    public bool TryGetFirstChargeDataByFirstId(int firstId, out FirstChargeData firstChargeData) 
 | 
    { 
 | 
        return firstChargeInfoDict.TryGetValue(firstId, out firstChargeData); 
 | 
    } 
 | 
  
 | 
    public bool TryGetUnBuyFirstId(out int firstId) 
 | 
    { 
 | 
        firstId = 0; 
 | 
        var firstChargeList = FirstChargeConfig.GetKeys(); 
 | 
        if (firstChargeList != null) 
 | 
        { 
 | 
            firstChargeList.Sort(); 
 | 
            foreach (int item in firstChargeList) 
 | 
            { 
 | 
                if (TryGetFirstChargeDataByFirstId(item, out FirstChargeData data)) 
 | 
                { 
 | 
                    if (data.IsUnlock() && !data.IsBuy()) 
 | 
                    { 
 | 
                        firstId = item; 
 | 
                        return true; 
 | 
                    } 
 | 
                } 
 | 
  
 | 
            } 
 | 
        } 
 | 
        return false; 
 | 
    } 
 | 
  
 | 
    /// <summary> 
 | 
    /// 根据标签页索引获取对应的首充ID 
 | 
    /// </summary> 
 | 
    /// <param name="tabIndex">标签页索引,从0开始</param> 
 | 
    /// <returns>对应的首充ID,从1开始</returns> 
 | 
    public int GetFirstIDByTabIndex(int tabIndex) 
 | 
    { 
 | 
        return tabIndex + 1; 
 | 
    } 
 | 
  
 | 
    /// <summary> 
 | 
    /// 根据首充ID获取对应的标签页索引 
 | 
    /// </summary> 
 | 
    /// <param name="firstId">首充ID,从1开始</param> 
 | 
    /// <returns>对应的标签页索引,从0开始</returns> 
 | 
    public int GetTabIndexByFirstID(int firstId) 
 | 
    { 
 | 
        return Math.Max(firstId - 1, 0); 
 | 
    } 
 | 
  
 | 
    public int GetLastFirstIDByTabIndex(int tabIndex) 
 | 
    { 
 | 
        return GetFirstIDByTabIndex(tabIndex == 0 ? tabIndex : tabIndex - 1); 
 | 
    } 
 | 
    public int GetNextFirstIDByTabIndex(int tabIndex) 
 | 
    { 
 | 
        return GetFirstIDByTabIndex(tabIndex >= maxGiftCount - 1 ? maxGiftCount - 1 : tabIndex + 1); 
 | 
    } 
 | 
    public int GetLastFirstIDByFirstID(int firstId) 
 | 
    { 
 | 
        int tabIndex = GetTabIndexByFirstID(firstId); 
 | 
        return GetLastFirstIDByTabIndex(tabIndex); 
 | 
    } 
 | 
    public int GetNextFirstIDByFirstID(int firstId) 
 | 
    { 
 | 
        int tabIndex = GetTabIndexByFirstID(firstId); 
 | 
        return GetNextFirstIDByTabIndex(tabIndex); 
 | 
    } 
 | 
  
 | 
    public bool TryGetFirstChargeConfigByFirstID(int firstId, out FirstChargeConfig firstChargeConfig) 
 | 
    { 
 | 
        firstChargeConfig = null; 
 | 
        if (!FirstChargeConfig.HasKey(firstId)) 
 | 
            return false; 
 | 
        firstChargeConfig = FirstChargeConfig.Get(firstId); 
 | 
        return true; 
 | 
    } 
 | 
  
 | 
    public bool TryGetOrderInfoConfigByFirstID(int firstId, out OrderInfoConfig orderInfoConfig) 
 | 
    { 
 | 
        orderInfoConfig = null; 
 | 
        if (!TryGetFirstChargeConfigByFirstID(firstId, out FirstChargeConfig firstChargeConfig)) 
 | 
            return false; 
 | 
        int ctgId = firstChargeConfig.CTGID; 
 | 
        return RechargeManager.Instance.TryGetOrderInfo(ctgId, out orderInfoConfig); 
 | 
    } 
 | 
  
 | 
    public bool TryGetCTGConfigByFirstID(int firstId, out CTGConfig ctgConfig) 
 | 
    { 
 | 
        ctgConfig = null; 
 | 
        if (!TryGetFirstChargeConfigByFirstID(firstId, out FirstChargeConfig firstChargeConfig)) 
 | 
            return false; 
 | 
        int ctgId = firstChargeConfig.CTGID; 
 | 
        if (!CTGConfig.HasKey(ctgId)) 
 | 
            return false; 
 | 
        ctgConfig = CTGConfig.Get(ctgId); 
 | 
        return true; 
 | 
    } 
 | 
    public int GetMainItemId() 
 | 
    { 
 | 
        var list = FirstChargeConfig.GetKeys(); 
 | 
        list.Sort(); 
 | 
        var config = FirstChargeConfig.Get(list[0]); 
 | 
        for (int i = 0; i < config.AwardListDay1.Length; i++) 
 | 
        { 
 | 
            int itemId = config.AwardListDay1[i][0]; 
 | 
            if (!ItemConfig.HasKey(itemId)) 
 | 
                continue; 
 | 
            if (ItemConfig.Get(itemId).Type == 150) 
 | 
            { 
 | 
                return itemId; 
 | 
            } 
 | 
        } 
 | 
        return 0; 
 | 
    } 
 | 
  
 | 
    public void UpdateFirstChargeInfo(HAA02_tagSCFirstChargeInfo vNetData) 
 | 
    { 
 | 
        if (vNetData.FirstChargeList.IsNullOrEmpty()) 
 | 
            return; 
 | 
        foreach (var chargeInfo in vNetData.FirstChargeList) 
 | 
        { 
 | 
            int firstID = chargeInfo.FirstID; 
 | 
            if (!firstChargeInfoDict.TryGetValue(firstID, out var firstChargeData)) 
 | 
            { 
 | 
                firstChargeData = new FirstChargeData(); 
 | 
                firstChargeInfoDict[firstID] = firstChargeData; 
 | 
            } 
 | 
            firstChargeData.FirstID = firstID; 
 | 
            firstChargeData.ChargeTime = chargeInfo.ChargeTime; 
 | 
            firstChargeData.AwardRecord = chargeInfo.AwardRecord; 
 | 
        } 
 | 
        // 检查是否所有奖励都已领取,如果是,则记录当前服务器时间到本地 
 | 
        CheckAndSaveAllRewardsClaimedTime(); 
 | 
        UpdateRedPoint(); 
 | 
        OnUpdateFirstChargeInfo?.Invoke(); 
 | 
    } 
 | 
  
 | 
    /// <summary> 
 | 
    /// 检查是否所有首充奖励都已领取,如果是,则将当前服务器时间保存到本地 
 | 
    /// </summary> 
 | 
    private void CheckAndSaveAllRewardsClaimedTime() 
 | 
    { 
 | 
        // 检查是否所有奖励都已领取 
 | 
        if (IsAllFirstChargeRewardsClaimed()) 
 | 
        { 
 | 
            // 生成一个唯一的键来存储时间 
 | 
            string key = $"FirstCharge_AllRewardsClaimed_Time_{PlayerDatas.Instance.baseData.PlayerID}"; 
 | 
            // 将当前服务器时间保存到本地 
 | 
            LocalSave.SetString(key, TimeUtility.ServerNow.Ticks.ToString()); 
 | 
        } 
 | 
    } 
 | 
    public void UpdateRedPoint() 
 | 
    { 
 | 
        // 重置所有红点状态 
 | 
        parentRedpoint.state = RedPointState.None; 
 | 
        foreach (var redpoint in tabRedpointDict.Values) 
 | 
        { 
 | 
            redpoint.state = RedPointState.None; 
 | 
        } 
 | 
  
 | 
        var firstChargeList = FirstChargeConfig.GetKeys(); 
 | 
        if (firstChargeList.IsNullOrEmpty()) 
 | 
            return; 
 | 
        firstChargeList.Sort(); 
 | 
        foreach (int firstId in firstChargeList) 
 | 
        { 
 | 
            if (!tabRedpointDict.ContainsKey(firstId)) 
 | 
                continue; 
 | 
            var redpoint = tabRedpointDict[firstId]; 
 | 
  
 | 
            if (TryGetFirstChargeDataByFirstId(firstId, out var firstChargeData)) 
 | 
            { 
 | 
                if (firstChargeData.IsBuy()) 
 | 
                { 
 | 
                    for (int day = 1; day <= maxDay; day++) 
 | 
                    { 
 | 
                        int awardState = firstChargeData.GetHaveState(day); 
 | 
                        // 2: 可领取 
 | 
                        if (awardState == 2) 
 | 
                        { 
 | 
                            redpoint.state = RedPointState.Simple; 
 | 
                            break; 
 | 
                        } 
 | 
                    } 
 | 
                } 
 | 
                else 
 | 
                { 
 | 
                    bool clickTabState = GetClickTabState(firstId); 
 | 
                    if (firstChargeData.IsUnlock() && !clickTabState) 
 | 
                    { 
 | 
                        redpoint.state = RedPointState.Simple; 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
  
 | 
  
 | 
        } 
 | 
    } 
 | 
  
 | 
    /// <summary> 
 | 
    /// 发送领取首充奖励请求 
 | 
    /// </summary> 
 | 
    /// <param name="day">要领取的奖励是第x天的, 从1开始</param> 
 | 
    /// <param name="firstID">首充表的ID</param> 
 | 
    public void SendGetReward(int day, int firstID) 
 | 
    { 
 | 
        var pack = new CA504_tagCMPlayerGetReward(); 
 | 
        pack.RewardType = 8; 
 | 
        pack.DataEx = (uint)day;//第x天,1代表第1天 
 | 
        string firstIdStr = firstID.ToString();//领取哪个首充ID,对应首充表的ID 
 | 
        pack.DataExStr = firstIdStr; 
 | 
        pack.DataExStrLen = (byte)firstIdStr.Length; 
 | 
        GameNetSystem.Instance.SendInfo(pack); 
 | 
    } 
 | 
  
 | 
    /// <summary> 
 | 
    /// 自动领取玩家可以领取的所有首充奖励 
 | 
    /// </summary> 
 | 
    /// <param name="firstID">首充表的ID</param> 
 | 
    public void AutoClaimAllRewards(int firstID) 
 | 
    { 
 | 
        if (!TryGetFirstChargeDataByFirstId(firstID, out var firstChargeData)) 
 | 
            return; 
 | 
        if (!firstChargeData.IsBuy()) 
 | 
            return; 
 | 
        // 获取当前是购买后的第几天 
 | 
        int currentDay = firstChargeData.GetNowBuyDay(); 
 | 
        // 遍历从第1天到当前天数的所有奖励 
 | 
        for (int day = 1; day <= maxDay; day++) 
 | 
        { 
 | 
            // 检查奖励状态,只有状态为已购买没领取才发送领取请求 
 | 
            if (day <= currentDay && firstChargeData.GetHaveState(day) == 2)//0: 已领取 1: 不可领取 2: 可领取  
 | 
            { 
 | 
                SendGetReward(day, firstID); 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    // 检查是否所有首充奖励都已经领取 
 | 
    public bool IsAllFirstChargeRewardsClaimed() 
 | 
    { 
 | 
        // 获取所有首充配置ID 
 | 
        var firstChargeIds = FirstChargeConfig.GetKeys(); 
 | 
        if (firstChargeIds == null || firstChargeIds.Count == 0) 
 | 
            return false; 
 | 
  
 | 
        foreach (var firstId in firstChargeIds) 
 | 
        { 
 | 
            // 尝试获取首充数据 
 | 
            if (!TryGetFirstChargeDataByFirstId(firstId, out var firstChargeData)) 
 | 
                return false; 
 | 
  
 | 
            // 检查是否购买 
 | 
            if (!firstChargeData.IsBuy()) 
 | 
                return false; 
 | 
  
 | 
            // 检查是否所有奖励都已领取 
 | 
            if (!firstChargeData.IsAllHave()) 
 | 
                return false; 
 | 
        } 
 | 
  
 | 
        // 所有首充档位都已购买且所有奖励都已领取 
 | 
        // 检查是否已经过了第二天0点 
 | 
        return true; 
 | 
    } 
 | 
  
 | 
    // 检查是否已经过了所有奖励领取完毕后的第二天0点 
 | 
    public bool IsNextDayAfterAllClaimed() 
 | 
    { 
 | 
        // 生成一个唯一的键来获取时间 
 | 
        string key = $"FirstCharge_AllRewardsClaimed_Time_{PlayerDatas.Instance.baseData.PlayerID}"; 
 | 
  
 | 
        // 检查是否存在记录的时间戳 
 | 
        if (!LocalSave.HasKey(key)) 
 | 
            return false; 
 | 
  
 | 
        // 获取记录的时间戳 
 | 
        string timeString = LocalSave.GetString(key); 
 | 
        if (string.IsNullOrEmpty(timeString)) 
 | 
            return false; 
 | 
  
 | 
        // 解析时间戳 
 | 
        if (!long.TryParse(timeString, out long ticks)) 
 | 
            return false; 
 | 
  
 | 
        // 将时间戳转换为DateTime 
 | 
        DateTime allRewardsClaimedTime = new DateTime(ticks); 
 | 
  
 | 
        // 计算第二天0点的时间 
 | 
        DateTime nextDayStart = allRewardsClaimedTime.Date.AddDays(1); 
 | 
  
 | 
        // 判断当前服务器时间是否已经过了第二天0点 
 | 
        DateTime serverNow = TimeUtility.ServerNow; 
 | 
        return serverNow >= nextDayStart; 
 | 
    } 
 | 
  
 | 
} 
 | 
public class FirstChargeData 
 | 
{ 
 | 
    public int FirstID;        //首充ID 
 | 
    public uint ChargeTime;        //充值该首充的时间戳 
 | 
    public ushort AwardRecord;        //首充奖励领奖记录,按二进制位记录首充第X天是否已领取(第1天对应第1位) 
 | 
  
 | 
    public bool IsUnlock() 
 | 
    { 
 | 
        int tabIndex = FirstChargeManager.Instance.GetTabIndexByFirstID(FirstID); 
 | 
        if (tabIndex == 0) 
 | 
            return true; 
 | 
        int lastFirstID = FirstChargeManager.Instance.GetLastFirstIDByTabIndex(tabIndex); 
 | 
        FirstChargeData firstChargeDataNow; 
 | 
        if (!FirstChargeManager.Instance.TryGetFirstChargeDataByFirstId(lastFirstID, out firstChargeDataNow)) 
 | 
            return false; 
 | 
        return firstChargeDataNow.IsBuy(); 
 | 
    } 
 | 
  
 | 
    public bool IsBuy() 
 | 
    { 
 | 
        return ChargeTime > 0; 
 | 
    } 
 | 
  
 | 
    /// <summary> 
 | 
    /// 检查指定天的奖励是否已领取 
 | 
    /// </summary> 
 | 
    /// <param name="day">天数,从1开始</param> 
 | 
    public bool IsHave(int day) 
 | 
    { 
 | 
        bool res = (AwardRecord & (1 << day)) != 0; 
 | 
        return res; 
 | 
    } 
 | 
  
 | 
    public bool IsAllHave() 
 | 
    { 
 | 
        int maxGiftCount = FirstChargeManager.Instance.maxGiftCount; 
 | 
        for (int i = 1; i <= maxGiftCount; i++) 
 | 
        { 
 | 
            if (!IsHave(i)) 
 | 
                return false; 
 | 
        } 
 | 
        return true; 
 | 
    } 
 | 
  
 | 
    // ... existing code ... 
 | 
    /// <summary> 
 | 
    /// 获取当前时间是购买这档充值礼包的第几天 
 | 
    /// 购买的当天算作第一天,第二天0点后算第二天,以此类推 
 | 
    /// </summary> 
 | 
    /// <returns>第几天</returns> 
 | 
    public int GetNowBuyDay() 
 | 
    { 
 | 
        DateTime serverNow = TimeUtility.ServerNow; 
 | 
        DateTime chargeTime = TimeUtility.GetTime(ChargeTime); 
 | 
  
 | 
        DateTime chargeDate = chargeTime.Date; 
 | 
        DateTime serverDate = serverNow.Date; 
 | 
  
 | 
        // 计算从充值日期到当前日期的完整天数 
 | 
        // 购买的当天算第一天,第二天0点后算第二天 
 | 
        TimeSpan timeSpan = serverDate - chargeDate; 
 | 
        int days = (int)timeSpan.TotalDays + 1; // +1 因为当天算第一天 
 | 
  
 | 
        int maxDay = FirstChargeManager.Instance.maxDay; 
 | 
  
 | 
        return Mathf.Min(maxDay, Mathf.Max(1, days)); 
 | 
    } 
 | 
  
 | 
    public bool HasNextDay() 
 | 
    { 
 | 
        int currentDay = GetNowBuyDay(); 
 | 
        int maxDay = FirstChargeManager.Instance.maxDay; 
 | 
        return currentDay < maxDay; 
 | 
    } 
 | 
  
 | 
    /// <summary> 
 | 
    /// 获得指定天的领取详细状态 
 | 
    /// </summary> 
 | 
    /// <param name="day">天数,从1开始</param> 
 | 
    //0: 已领取 1: 不可领取 2: 可领取  
 | 
    public int GetHaveState(int day) 
 | 
    { 
 | 
        if (IsHave(day)) 
 | 
            return 0; 
 | 
        int currentDay = GetNowBuyDay(); 
 | 
        // 检查是否可以领取(购买这档充值礼包的第一天后才可领取) 
 | 
        return day <= currentDay ? 2 : 1; 
 | 
    } 
 | 
  
 | 
    /// <summary> 
 | 
    /// 返回显示距离第二天0点解锁奖励剩余时间 
 | 
    /// </summary> 
 | 
    /// <returns>剩余时间字符串,格式:小时:分钟:秒钟</returns> 
 | 
    public string GetNextDayUnlockRemainingTime() 
 | 
    { 
 | 
        if (!IsBuy()) 
 | 
            return string.Empty; 
 | 
        DateTime serverNow = TimeUtility.ServerNow; 
 | 
        DateTime nextDayStart = serverNow.Date.AddDays(1); 
 | 
        TimeSpan remainingTime = nextDayStart - serverNow; 
 | 
        int remainingSeconds = (int)remainingTime.TotalSeconds; 
 | 
        return TimeUtility.SecondsToHMS(remainingSeconds); 
 | 
    } 
 | 
  
 | 
} 
 |