context: using System;
  using System.Globalization;
  using UnityEngine;
  using Sabresaurus.PlayerPrefsExtensions;
  
  public static class PlayerPrefsUtility
  {
  	// Each encrypted player pref key is given a prefix (this helps the Editor to identify them)
  	public const string KEY_PREFIX = "ENC-";
  
  	// Each encrypted value is prefixed with a type identifier (because encrypted values are stored as strings)
  	public const string VALUE_FLOAT_PREFIX = "0";
  	public const string VALUE_INT_PREFIX = "1";
  	public const string VALUE_STRING_PREFIX = "2";
  
  	/// <summary>
  	/// Determines if the specified player pref key refers to an encrypted record
  	/// </summary>
  	public static bool IsEncryptedKey (string key)
  	{
  		// Encrypted keys use a special prefix
  		if(key.StartsWith(KEY_PREFIX))
  		{
  			return true;
  		}
  		else
  		{
  			return false;
  		}
  	}
  
  	/// <summary>
  	/// Decrypts the specified key
  	/// </summary>
  	public static string DecryptKey(string encryptedKey)
  	{
  		if(encryptedKey.StartsWith(KEY_PREFIX))
  		{
  			// Remove the key prefix from the encrypted key
  			string strippedKey = encryptedKey.Substring(KEY_PREFIX.Length);
  			// Return the decrypted key
  			return SimpleEncryption.DecryptString(strippedKey);
  		}
  		else
  		{
  			throw new InvalidOperationException("Could not decrypt item, no match found in known encrypted key prefixes");
  		}
  	}
  
  	/// <summary>
  	/// Encrypted version of PlayerPrefs.SetFloat(), stored key and value is encrypted in player prefs
  	/// </summary>
  	public static void SetEncryptedFloat(string key, float value)
  	{
  		string encryptedKey = SimpleEncryption.EncryptString(key);
  		string encryptedValue = SimpleEncryption.EncryptFloat(value);
  
  		// Store the encrypted key and value (with relevant identifying prefixes) in PlayerPrefs
  		PlayerPrefs.SetString(KEY_PREFIX + encryptedKey, VALUE_FLOAT_PREFIX + encryptedValue);
  	}
  
  	/// <summary>
  	/// Encrypted version of PlayerPrefs.SetInt(), stored key and value is encrypted in player prefs
  	/// </summary>
  	public static void SetEncryptedInt(string key, int value)
  	{
  		string encryptedKey = SimpleEncryption.EncryptString(key);
  		string encryptedValue = SimpleEncryption.EncryptInt(value);
  
  		// Store the encrypted key and value (with relevant identifying prefixes) in PlayerPrefs
  		PlayerPrefs.SetString(KEY_PREFIX + encryptedKey, VALUE_INT_PREFIX + encryptedValue);
  	}
  
  	/// <summary>
  	/// Encrypted version of PlayerPrefs.SetString(), stored key and value is encrypted in player prefs
  	/// </summary>
  	public static void SetEncryptedString(string key, string value)
  	{
  		string encryptedKey = SimpleEncryption.EncryptString(key);
  		string encryptedValue = SimpleEncryption.EncryptString(value);
  
  		// Store the encrypted key and value (with relevant identifying prefixes) in PlayerPrefs
  		PlayerPrefs.SetString(KEY_PREFIX + encryptedKey, VALUE_STRING_PREFIX + encryptedValue);
  	}
  
  	/// <summary>
  	/// Helper method that can handle any of the encrypted player pref types, returning a float, int or string based
  	/// on what type of value has been stored.
  	/// </summary>
  	public static object GetEncryptedValue(string encryptedKey, string encryptedValue)
  	{
  		// See what type identifier the encrypted value starts
  		if(encryptedValue.StartsWith(VALUE_FLOAT_PREFIX))
  		{
  			// It's a float, so decrypt it as a float and return the value
  			return GetEncryptedFloat(SimpleEncryption.DecryptString(encryptedKey.Substring(KEY_PREFIX.Length)));
  		}
  		else if(encryptedValue.StartsWith(VALUE_INT_PREFIX))
  		{
  			// It's an int, so decrypt it as an int and return the value
  			return GetEncryptedInt(SimpleEncryption.DecryptString(encryptedKey.Substring(KEY_PREFIX.Length)));
  		}
  		else if(encryptedValue.StartsWith(VALUE_STRING_PREFIX))
  		{
  			// It's a string, so decrypt it as a string and return the value
  			return GetEncryptedString(SimpleEncryption.DecryptString(encryptedKey.Substring(KEY_PREFIX.Length)));
  		}
  		else
  		{
  			throw new InvalidOperationException("Could not decrypt item, no match found in known encrypted key prefixes");
  		}
  	}
  
  	/// <summary>
  	/// Encrypted version of PlayerPrefs.GetFloat(), an unencrypted key is passed and the value is returned decrypted
  	/// </summary>
  	public static float GetEncryptedFloat(string key, float defaultValue = 0.0f)
  	{
  		// Encrypt and prefix the key so we can look it up from player prefs
  		string encryptedKey = KEY_PREFIX + SimpleEncryption.EncryptString(key);
  
  		// Look up the encrypted value
  		string fetchedString = PlayerPrefs.GetString(encryptedKey);
  
  		if(!string.IsNullOrEmpty(fetchedString))
  		{
  			// Strip out the type identifier character
  			fetchedString = fetchedString.Remove(0, 1);
  
  			// Decrypt and return the float value
  			return SimpleEncryption.DecryptFloat (fetchedString);
  		}
  		else
  		{
  			// No existing player pref value, so return defaultValue instead
  			return defaultValue;
  		}
  	}
  
  	/// <summary>
  	/// Encrypted version of PlayerPrefs.GetInt(), an unencrypted key is passed and the value is returned decrypted
  	/// </summary>
  	public static int GetEncryptedInt(string key, int defaultValue = 0)
  	{
  		// Encrypt and prefix the key so we can look it up from player prefs
  		string encryptedKey = KEY_PREFIX + SimpleEncryption.EncryptString(key);
  		
  		// Look up the encrypted value
  		string fetchedString = PlayerPrefs.GetString(encryptedKey);
  
  		if(!string.IsNullOrEmpty(fetchedString))
  		{
  			// Strip out the type identifier character
  			fetchedString = fetchedString.Remove(0, 1);
  
  			// Decrypt and return the int value
  			return SimpleEncryption.DecryptInt (fetchedString);
  		}
  		else
  		{
  			// No existing player pref value, so return defaultValue instead
  			return defaultValue;
  		}
  	}
  
  	/// <summary>
  	/// Encrypted version of PlayerPrefs.GetString(), an unencrypted key is passed and the value is returned decrypted
  	/// </summary>
  	public static string GetEncryptedString(string key, string defaultValue = "")
  	{
  		// Encrypt and prefix the key so we can look it up from player prefs
  		string encryptedKey = KEY_PREFIX + SimpleEncryption.EncryptString(key);
  		
  		// Look up the encrypted value
  		string fetchedString = PlayerPrefs.GetString(encryptedKey);
  
  		if(!string.IsNullOrEmpty(fetchedString))
  		{
  			// Strip out the type identifier character
  			fetchedString = fetchedString.Remove(0, 1);
  
  			// Decrypt and return the string value
  			return SimpleEncryption.DecryptString (fetchedString);
  		}
  		else
  		{
  			// No existing player pref value, so return defaultValue instead
  			return defaultValue;
  		}
  	}
  
  	/// <summary>
  	/// Helper method to store a bool in PlayerPrefs (stored as an int)
  	/// </summary>
  	public static void SetBool(string key, bool value)
  	{
  		// Store the bool as an int (1 for true, 0 for false)
  		if(value)
  		{
  			PlayerPrefs.SetInt(key, 1);
  		}
  		else
  		{
  			PlayerPrefs.SetInt(key, 0);
  		}
  	}
  
  	/// <summary>
  	/// Helper method to retrieve a bool from PlayerPrefs (stored as an int)
  	/// </summary>
  	public static bool GetBool(string key, bool defaultValue = false)
  	{
  		// Use HasKey to check if the bool has been stored (as int defaults to 0 which is ambiguous with a stored False)
  		if(PlayerPrefs.HasKey(key))
  		{
  			int value = PlayerPrefs.GetInt(key);
  
  			// As in C, assume zero is false and any non-zero value (including its intended 1) is true
  			if(value != 0)
  			{
  				return true;
  			}
  			else
  			{
  				return false;
  			}
  		}
  		else
  		{
  			// No existing player pref value, so return defaultValue instead
  			return defaultValue;
  		}
  	}
  
  	/// <summary>
  	/// Helper method to store an enum value in PlayerPrefs (stored using the string name of the enum)
  	/// </summary>
  	public static void SetEnum(string key, Enum value)
  	{
  		// Convert the enum value to its string name (as opposed to integer index) and store it in a string PlayerPref
  		PlayerPrefs.SetString(key, value.ToString());
  	}
  
  	/// <summary>
  	/// Generic helper method to retrieve an enum value from PlayerPrefs and parse it from its stored string into the 
  	/// specified generic type. This method should generally be preferred over the non-generic equivalent
  	/// </summary>
  	public static T GetEnum<T>(string key, T defaultValue = default(T)) where T: struct 
  	{
  		// Fetch the string value from PlayerPrefs
  		string stringValue = PlayerPrefs.GetString (key);
  
  		if(!string.IsNullOrEmpty(stringValue))
  		{
  			// Existing value, so parse it using the supplied generic type and cast before returning it
  			return (T)Enum.Parse(typeof(T), stringValue);
  		}
  		else 
  		{
  			// No player pref for this, just return default. If no default is supplied this will be the enum's default
  			return defaultValue;
  		}
  	}
  
  	/// <summary>
  	/// Non-generic helper method to retrieve an enum value from PlayerPrefs (stored as a string). Default value must be
  	/// passed, passing null will mean you need to do a null check where you call this method. Generally try to use the
  	/// generic version of this method instead: GetEnum<T>
  	/// </summary>
  	public static object GetEnum(string key, Type enumType, object defaultValue)
  	{
  		// Fetch the string value from PlayerPrefs
  		string value = PlayerPrefs.GetString (key);
  
  		if(!string.IsNullOrEmpty(value))
  		{
  			// Existing value, parse it using the supplied type, then return the result as an object
  			return Enum.Parse(enumType, value);
  		}
  		else
  		{
  			// No player pref for this key, so just return supplied default. It's required to supply a default value,
  			// you can just pass null, but you would then need to do a null check where you call non-generic GetEnum().
  			// Consider using GetEnum<T>() which doesn't require a default to be passed (supplying default(T) instead)
  			return defaultValue;
  		}
  	}
  
  	/// <summary>
  	/// Helper method to store a DateTime (complete with its timezone) in PlayerPrefs as a string
  	/// </summary>
  	public static void SetDateTime(string key, DateTime value)
  	{
  		// Convert to an ISO 8601 compliant string ("o"), so that it's fully qualified, then store in PlayerPrefs
  		PlayerPrefs.SetString(key, value.ToString("o", CultureInfo.InvariantCulture));
  	}
  
  	/// <summary>
  	/// Helper method to retrieve a DateTime from PlayerPrefs (stored as a string) and return a DateTime complete with
  	/// timezone (works with UTC and local DateTimes)
  	/// </summary>
  	public static DateTime GetDateTime(string key, DateTime defaultValue = new DateTime())
  	{
  		// Fetch the string value from PlayerPrefs
  
gt: 		string stringValue = PlayerPrefs.GetString(key);