using System; using System.Collections.Generic; using System.Diagnostics; using SUISS.Core; using SUISS.Core.Utilities; using SUISS.Scheduling; using SUISS.Storage; using SUISSEngine; using UnityEngine; public sealed class IAPPackDealManager : Singleton { public IAPPackDealManager() { if (this.HasDeal) { this._timer = SingletonMonobehaviour.Instance.CreateClockTimer(this.FirstActiveDeal.DealStart + this.FirstActiveDeal.DealDuration, new Action(this.DealEndTimer)); } } //[DebuggerBrowsable(DebuggerBrowsableState.Never)] public event IAPPackDealManager.DealStartedHandler DealStartedEvent; private void FireDealStartedEvent(IAPPackDealManager.PackDeal deal) { if (this.DealStartedEvent != null) { this.DealStartedEvent(deal.PackName, deal.DealStart, deal.DealDuration); } } //[DebuggerBrowsable(DebuggerBrowsableState.Never)] public event IAPPackDealManager.DealEndedHandler DealEndedEvent; private void FireDealEndedEvent(IAPPackDealManager.PackDeal deal) { if (this.DealEndedEvent != null && deal != null) { this.DealEndedEvent(deal.PackName); } } public IAPPackDealManager.PackDeal FindFirstActive(string packName) { int count = this.ActiveDeals.Count; for (int i = 0; i < count; i++) { if (this.ActiveDeals[i].PackName == packName) { return this.ActiveDeals[i]; } } return null; } public bool StartDeal(string packName, TimeSpan duration) { this.StartScheduledDealsRoutine(); if (!IAPPackManager.Instance.AllPackNames.Contains(packName)) { UnityEngine.Debug.LogError(string.Format("Tried to start IAP pack deal unknown to the IAPPackDealManager", packName)); return false; } IAPPackDealManager.PackDeal packDeal = new IAPPackDealManager.PackDeal(packName, duration, DateTime.UtcNow); IList activeDeals = this.ActiveDeals; activeDeals.Add(packDeal); this.ActiveDeals = activeDeals; this.FireDealStartedEvent(packDeal); if (this._timer != null) { this._timer.Cancel(); this._timer = null; } IAPPackDealManager.PackDeal firstActiveDeal = this.FirstActiveDeal; if (firstActiveDeal != null) { this._timer = SingletonMonobehaviour.Instance.CreateClockTimer(firstActiveDeal.DealStart + firstActiveDeal.DealDuration, new Action(this.DealEndTimer)); return true; } return false; } public void ScheduleDeal(string packName, TimeSpan duration, DateTime time) { this.StartScheduledDealsRoutine(); List list = this.ScheduledDeals as List; list.Add(new IAPPackDealManager.PackDeal(packName, duration, time)); list.Sort(delegate(IAPPackDealManager.PackDeal lhs, IAPPackDealManager.PackDeal rhs) { if (lhs.DealDuration < rhs.DealDuration) { return -1; } if (lhs.DealDuration > rhs.DealDuration) { return 1; } return 0; }); this.ScheduledDeals = list; } public void EndDeal(IAPPackDealManager.PackDeal deal) { List list = this.ActiveDeals.ToList(); IAPPackDealManager.PackDeal packDeal = list.Find((IAPPackDealManager.PackDeal d) => d.IsMatch(deal)); if (packDeal == null) { UnityEngine.Debug.LogErrorFormat("Deal with packName {0} not found", new object[] { deal.PackName }); return; } list.Remove(packDeal); this.ActiveDeals = list; if (packDeal == this.FirstActiveDeal && this._timer != null) { this._timer.Cancel(); this._timer = null; } if (list.Count != 0) { IAPPackDealManager.PackDeal firstActiveDeal = this.FirstActiveDeal; this._timer = SingletonMonobehaviour.Instance.CreateClockTimer(firstActiveDeal.DealStart + firstActiveDeal.DealDuration, new Action(this.DealEndTimer)); } this.FireDealEndedEvent(packDeal); } public IList ActiveDeals { get { Dictionary storage = this._storage; List list = new List(); if (!storage.ContainsKey("ActiveSales")) { return list; } List list2 = storage["ActiveSales"] as List; int count = list2.Count; for (int i = 0; i < count; i++) { object obj = list2[i]; if (obj == null) { UnityEngine.Debug.LogError("Found a null object in storage."); } else if (!(obj is Dictionary)) { UnityEngine.Debug.LogError(string.Format("Found an object of type '{0}' in storage. Should be Dictionary", obj.GetType())); } else { IAPPackDealManager.PackDeal packDeal = IAPPackDealManager.PackDeal.FromDictionary((Dictionary)obj); if (!(DateTime.UtcNow > packDeal.DealStart + packDeal.DealDuration)) { list.Add(packDeal); } } } return list; } private set { List list = new List(); int count = value.Count; for (int i = 0; i < count; i++) { list.Add(IAPPackDealManager.PackDeal.ToDictionary(value[i])); } this._storage["ActiveSales"] = list; } } public bool HasDeal { get { return this.ActiveDeals.Count != 0; } } public IAPPackDealManager.PackDeal FirstActiveDeal { get { Dictionary storage = this._storage; IList activeDeals = this.ActiveDeals; if (storage.ContainsKey("PackForSale") && storage.ContainsKey("SaleStartTime") && storage.ContainsKey("SaleDurationKey")) { DateTime dateTime = new DateTime((long)storage["SaleStartTime"], DateTimeKind.Utc); TimeSpan timeSpan = new TimeSpan((long)storage["SaleDurationKey"]); if (DateTime.UtcNow >= dateTime && DateTime.UtcNow <= dateTime + timeSpan) { activeDeals.Add(new IAPPackDealManager.PackDeal(storage["PackForSale"] as string, timeSpan, dateTime)); this.ActiveDeals = activeDeals; } storage.Remove("PackForSale"); storage.Remove("SaleStartTime"); storage.Remove("SaleDurationKey"); } if (activeDeals.Count == 0) { return null; } return activeDeals.MinOrMaxObject((IAPPackDealManager.PackDeal x) => x.DealStart + x.DealDuration, true); } } private void StartScheduledDealsRoutine() { if (this._routineBeingStarted || this._dealsRoutine != null) { return; } IScheduler scheduler = ServiceLocator.Find(); if (scheduler != null) { this._routineBeingStarted = true; this._dealsRoutine = scheduler.StartCoroutine(this.CoScheduledDealsRoutine()); this._routineBeingStarted = false; } else { UnityEngine.Debug.LogWarning("IAPPackDealManger was unable to start deal timers because IScheduler is null in ServiceLocator."); } } private IEnumerator CoScheduledDealsRoutine() { for (;;) { while (this.ScheduledDeals.Count == 0) { yield return CoYield.On(1f); } IAPPackDealManager.PackDeal deal = this.ScheduledDeals[0]; if (DateTime.UtcNow <= deal.DealStart + deal.DealDuration) { while (DateTime.UtcNow < deal.DealStart) { yield return CoYield.On(1f); } if (!this.StartDeal(deal.PackName, deal.DealDuration - (DateTime.UtcNow - deal.DealStart))) { UnityEngine.Debug.LogError("No such deal name: " + deal.PackName); } } IList scheduledDeals = this.ScheduledDeals; scheduledDeals.Remove(deal); this.ScheduledDeals = scheduledDeals; } yield break; } private void DealEndTimer() { if (this._timer != null) { this._timer.Cancel(); this._timer = null; } if (this.FirstActiveDeal != null) { this.EndDeal(this.FirstActiveDeal); } } private Dictionary _storage { get { return Storage.Get(StorageLifecycle.Game).GetDictionary("Storage"); } } private IList ScheduledDeals { get { Dictionary storage = this._storage; List list = new List(); if (!storage.ContainsKey("ScheduledSales")) { return list; } List list2 = storage["ScheduledSales"] as List; int count = list2.Count; for (int i = 0; i < count; i++) { object obj = list2[i]; if (obj == null) { UnityEngine.Debug.LogError("Found a null object in storage."); } else if (!(obj is Dictionary)) { UnityEngine.Debug.LogError(string.Format("Found an object of type '{0}' in storage. Should be Dictionary", obj.GetType())); } else { IAPPackDealManager.PackDeal packDeal = IAPPackDealManager.PackDeal.FromDictionary((Dictionary)obj); if (!(DateTime.UtcNow > packDeal.DealStart + packDeal.DealDuration)) { list.Add(packDeal); } } } return list; } set { List list = new List(); int count = value.Count; for (int i = 0; i < count; i++) { list.Add(IAPPackDealManager.PackDeal.ToDictionary(value[i])); } this._storage["ScheduledSales"] = list; } } public const string StorageKey = "Storage"; public const string ScheduledDealsKey = "ScheduledSales"; public const string ActiveDealsKey = "ActiveSales"; public const string PackForSaleKey = "PackForSale"; public const string SaleStartTimeKey = "SaleStartTime"; public const string SaleDurationKey = "SaleDurationKey"; private bool _routineBeingStarted; private Timer _timer; private ICoroutine _dealsRoutine; public delegate void DealStartedHandler(string packName, DateTime start, TimeSpan duration); public delegate void DealEndedHandler(string oldPackName); public class PackDeal { public PackDeal() { } public PackDeal(string packName, TimeSpan duration, DateTime time) { this.PackName = packName; this.DealDuration = duration; this.DealStart = time; } public static IAPPackDealManager.PackDeal FromDictionary(Dictionary dict) { return new IAPPackDealManager.PackDeal { PackName = (string)dict["PackName"], DealDuration = new TimeSpan((long)dict["SaleDuration"]), DealStart = new DateTime((long)dict["SaleTime"], DateTimeKind.Utc) }; } public static Dictionary ToDictionary(IAPPackDealManager.PackDeal deal) { Dictionary dictionary = new Dictionary(); dictionary["PackName"] = deal.PackName; dictionary["SaleDuration"] = deal.DealDuration.Ticks; dictionary["SaleTime"] = deal.DealStart.Ticks; return dictionary; } public bool IsMatch(IAPPackDealManager.PackDeal packDeal) { return packDeal != null && packDeal.PackName == this.PackName && packDeal.DealDuration == this.DealDuration && packDeal.DealStart == this.DealStart; } public void Extend(TimeSpan addedDuration) { this.DealDuration += addedDuration; } public string PackName { get; private set; } public TimeSpan DealDuration { get; private set; } public DateTime DealStart { get; private set; } public DateTime DealEnds { get { return this.DealStart + this.DealDuration; } } public const string PackNameKey = "PackName"; public const string DealDurationKey = "SaleDuration"; public const string DealTimeKey = "SaleTime"; } }