using System.Collections.Generic;
using UnityEngine;
namespace Ubisoft
{
///
/// Class responsible for managing all IHtPlayerPrefs objects.
///
/// In order to keep preferences from getting accidentally overriden consumers are allowed to have only one IHtPlayerPrefs object
/// per channel. This can be guaranteed by allowing consumers to get an IHtPlayerPrefs instance only via this class.
///
/// Please, call Destroy() once you are done with this class, typically right before restarting your app, in order to make sure that
/// all IHtPlayerPrefs are saved and destroyed properly so you can restart your app clean.
///
public class HtPlayerPrefsService : HtSingletonHolder.IConsumer
{
public enum EError
{
None,
PlayerPrefsForChannelAlreadyExist
}
public delegate void OnCreateDelegate(string channel, EError error, IHtPlayerPrefs playerPrefs);
private HtPlayerPrefsFactory Factory { get; set; }
private List Catalog { get; }
private HtPlayerPrefsMonoBehaviour MonoBehaviour { get; set; }
public HtPlayerPrefsService(HtPlayerPrefsFactory factory)
{
Factory = factory;
Catalog = new List();
// MonoBehaviour is created to take care of key Unity events.
MonoBehaviour = HtSingletonHolder.AddMainComponent(this);
MonoBehaviour.Init(this);
}
~HtPlayerPrefsService()
{
InternalDestroy(false);
}
///
/// Save and destroy all IHtPlayePrefs objects. Please, call this method right before restarting your app.
///
public void Destroy()
{
InternalDestroy(true);
}
private void InternalDestroy(bool destroyMonoBehaviour)
{
if (MonoBehaviour != null)
{
HtSingletonHolder.RemoveMainComponent(destroyMonoBehaviour);
MonoBehaviour = null;
}
if (Catalog != null)
{
int count = Catalog.Count;
for (int i = 0; i < count; ++i)
{
// Save it before destroying it
if (Catalog[i].NeedsToSave)
{
Catalog[i].Save();
}
}
Catalog.Clear();
}
Factory = null;
}
///
/// Create an IHtPlayerPrefs> instance by using the config associated to the requested channel.
/// This task is asynchronous as some IHtPlayerPrefs implementations may need to communicate with Server.
///
/// PlayePrefs channel to save preferences to.
/// Delegate to call once the object is ready.
public void CreatePlayerPrefs(string channel, OnCreateDelegate onCreateDelegate)
{
EError error = EError.None;
IHtPlayerPrefs returnValue = null;
// Only an instance per channel is allowed to keep this channel preferences from getting accidentally overriden.
if (GetPlayerPrefs(channel) == null)
{
returnValue = Factory.Create(channel);
Catalog.Add(returnValue);
}
else
{
error = EError.PlayerPrefsForChannelAlreadyExist;
Factory.Logger.LogError($"An instance for channel {Debug.FormatTextInUserContext(channel)} already exists.");
}
onCreateDelegate?.Invoke(channel, error, returnValue);
}
///
/// Destroy the instance used for the channel passed in, if it exists.
///
/// PlayePrefs channel to destroy.
public void DestroyPlayerPrefs(string channel)
{
IHtPlayerPrefs prefs = GetPlayerPrefs(channel);
if (prefs != null)
{
// Save it before destroying it
if (prefs.NeedsToSave)
{
prefs.Save();
}
_ = Catalog.Remove(prefs);
}
}
///
/// Retrieve the IHtPlayerPrefs object used for the channel passed in, if it exists.
/// You need to have called CreatePlayerPrefs() before calling this method.
///
/// PlayerPrefs channel to retrieve.
/// The instance of IHtPlayerPrefs responsible for saving this channel preferences, if it exists", otherwise null.
public IHtPlayerPrefs GetPlayerPrefs(string channel)
{
IHtPlayerPrefs returnValue = null;
int count = Catalog.Count;
for (int i = 0; i < count && returnValue == null; ++i)
{
if (Catalog[i].Channel.Equals(channel))
{
returnValue = Catalog[i];
}
}
return returnValue;
}
///
/// Delete preferences for all channels that are currently in memory.
///
public void DeleteAllPlayerPrefs()
{
int count = Catalog.Count;
for (int i = 0; i < count; ++i)
{
Catalog[i].DeleteAll();
}
}
///
/// Save all channel preferences that are currently in memory.
///
public void SaveAllPlayerPrefs()
{
InternalSave(true);
}
///
/// Callbak called when HtSingletonHolder is destroyed.
///
/// Consumers shouldn't call this method.
///
/// Component that is about to be destroyed.
public void DestroySingleton(Component singleton)
{
if (singleton == MonoBehaviour)
{
MonoBehaviour = null;
}
}
internal void Update()
{
InternalSave(false);
}
private void InternalSave(bool force)
{
// Make sure that all IHtPlayerPref objects save their preferences if AutomaticSave is enabled.
int count = Catalog.Count;
for (int i = 0; i < count; ++i)
{
Catalog[i].Update();
if ((force || Catalog[i].AutomaticSave) && Catalog[i].NeedsToSave)
{
Catalog[i].Save();
}
}
}
}
}