using Assets.RoR2.Scripts.Platform;
using RoR2.EntitlementManagement;
using RoR2.ExpansionManagement;

namespace RoR2.Achievements;

public abstract class BaseAchievement
{
	public UserAchievementManager owner;

	public bool shouldGrant;

	public bool shouldUpdateProgress;

	public AchievementDef achievementDef;

	private bool _meetsBodyRequirement;

	protected LocalUser localUser { get; private set; }

	protected UserProfile userProfile { get; private set; }

	protected bool isUserAlive
	{
		get
		{
			if (localUser != null && (bool)localUser.cachedBody && (bool)localUser.cachedBody.healthComponent)
			{
				return localUser.cachedBody.healthComponent.alive;
			}
			return false;
		}
	}

	protected BodyIndex requiredBodyIndex { get; private set; } = BodyIndex.None;


	protected bool meetsBodyRequirement
	{
		get
		{
			return _meetsBodyRequirement;
		}
		set
		{
			if (_meetsBodyRequirement != value)
			{
				_meetsBodyRequirement = value;
				if (_meetsBodyRequirement)
				{
					OnBodyRequirementMet();
				}
				else
				{
					OnBodyRequirementBroken();
				}
			}
		}
	}

	protected virtual bool wantsBodyCallbacks { get; }

	public virtual void OnInstall()
	{
		localUser = owner.localUser;
		userProfile = owner.userProfile;
		requiredBodyIndex = LookUpRequiredBodyIndex();
		if (requiredBodyIndex != BodyIndex.None)
		{
			localUser.onBodyChanged += HandleBodyChangedForBodyRequirement;
			Run.onRunDestroyGlobal += SetBodyRequirementBrokenOnRunEnd;
		}
	}

	public virtual bool IsProgressiveAchievement()
	{
		return false;
	}

	public virtual float ProgressForAchievement()
	{
		return 0f;
	}

	public virtual ulong GetCurrentProgress()
	{
		return 0uL;
	}

	public virtual ulong GetProgressRequirement()
	{
		return 100uL;
	}

	public virtual void OnUninstall()
	{
		if (achievementDef.serverTrackerType != null)
		{
			SetServerTracked(shouldTrack: false);
		}
		if (requiredBodyIndex != BodyIndex.None)
		{
			Run.onRunDestroyGlobal -= SetBodyRequirementBrokenOnRunEnd;
			localUser.onBodyChanged -= HandleBodyChangedForBodyRequirement;
			meetsBodyRequirement = false;
		}
		owner = null;
		localUser = null;
		userProfile = null;
	}

	public void Grant()
	{
		if (shouldGrant)
		{
			return;
		}
		UnlockableDef unlockableDef = UnlockableCatalog.GetUnlockableDef(achievementDef.unlockableRewardIdentifier);
		if ((bool)unlockableDef)
		{
			ExpansionDef expansionDefForUnlockable = UnlockableCatalog.GetExpansionDefForUnlockable(unlockableDef.index);
			if ((bool)expansionDefForUnlockable && (bool)expansionDefForUnlockable.requiredEntitlement && !EntitlementManager.localUserEntitlementTracker.AnyUserHasEntitlement(expansionDefForUnlockable.requiredEntitlement))
			{
				return;
			}
		}
		if (!localUser.currentNetworkUser || localUser.currentNetworkUser.isParticipating)
		{
			shouldGrant = true;
			owner.dirtyGrantsCount++;
		}
	}

	public virtual void OnGranted()
	{
		if (!string.IsNullOrEmpty(achievementDef.unlockableRewardIdentifier))
		{
			if ((bool)localUser.currentNetworkUser)
			{
				UnlockableDef unlockableDef = UnlockableCatalog.GetUnlockableDef(achievementDef.unlockableRewardIdentifier);
				localUser.currentNetworkUser.CallCmdReportUnlock(unlockableDef.index);
			}
			BaseActivitySelector baseActivitySelector = new BaseActivitySelector();
			string[] childAchievementIdentifiers = achievementDef.childAchievementIdentifiers;
			foreach (string activityAchievementID in childAchievementIdentifiers)
			{
				baseActivitySelector.activityAchievementID = activityAchievementID;
				PlatformSystems.activityManager.TryToSetActivityAvailability(baseActivitySelector, newAvailability: true);
			}
			userProfile.AddUnlockToken(achievementDef.unlockableRewardIdentifier);
		}
		if (achievementDef.lunarCoinReward != 0 && (bool)localUser.currentNetworkUser)
		{
			localUser.currentNetworkUser.CallCmdAwardLunarCoins(achievementDef.lunarCoinReward);
		}
	}

	public void UpdateProgress()
	{
	}

	public virtual void TryToCompleteActivity()
	{
	}

	public void SetServerTracked(bool shouldTrack)
	{
		owner.SetServerAchievementTracked(achievementDef.serverIndex, shouldTrack);
	}

	protected virtual BodyIndex LookUpRequiredBodyIndex()
	{
		return BodyIndex.None;
	}

	private void HandleBodyChangedForBodyRequirement()
	{
		bool num = localUser.cachedBody;
		bool flag = meetsBodyRequirement;
		if (num)
		{
			flag = localUser.cachedBody.bodyIndex == requiredBodyIndex;
		}
		meetsBodyRequirement = flag;
	}

	protected virtual void OnBodyRequirementMet()
	{
	}

	protected virtual void OnBodyRequirementBroken()
	{
	}

	private void SetBodyRequirementBrokenOnRunEnd(Run run)
	{
		meetsBodyRequirement = false;
	}
}
