/*
 * +================================================================================+
 *      __  ___  ______________  __  __  ______________   ____
 *     / / / / |/ /  _/_  __/\ \/ / / / / /_  __/  _/ /  / __/
 *    / /_/ /    // /  / /    \  / / /_/ / / / _/ // /___\ \
 *    \____/_/|_/___/ /_/     /_/  \____/ /_/ /___/____/___/
 *
 * +================================================================================+
 *
 *    "THE BEER-WARE LICENSE"
 *    -----------------------
 *
 *    As long as you retain this notice you can do whatever you want with this
 *    stuff. However it is expressly forbidden to sell or commercially distribute
 *    Unity Utils or parts of it apart from your games.
 *    If you meet any of the authors some day, and you think this stuff is
 *    worth it, you can buy them a beer in return.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 *    THE SOFTWARE.
 *
 * +================================================================================+
 *
 *    Authors:
 *    David Krummenacher (dave@timbookedtwo.com)
 *
 */

using System;
using System.Collections.Generic;
using UnityEngine;

namespace Utils.Settings {

	/// <summary>
	/// Settings class. Use this to access and handle settings.
	/// Derive from the Setting class to create your own settings.
	/// The settings are handled in this way (Settings container instead of static settings classes or settings singletons)
	/// to prevent writing settings that aren't actually needed in the project and to easily apply all settings.
	/// </summary>
	public abstract class Settings {

		/// <summary>
		/// The settings mapping.
		/// </summary>
		private static Dictionary<Type, Setting> settings;

		/// <summary>
		/// Static constructor.
		/// </summary>
		static Settings() {
			settings = new Dictionary<Type, Setting>();
		}

		/// <summary>
		/// Get a setting of a given type.
		/// </summary>
		/// <returns>The setting.</returns>
		/// <typeparam name="T">The type of the setting.</typeparam>
		public static T GetSetting<T>() where T : Setting, new() {
			// Look for setting
			if (settings.ContainsKey(typeof(T))) return (T) settings[typeof(T)];
			
			// Create new setting if it wasn't found
			T newSetting = new T();
			settings.Add(typeof(T), newSetting);
			return newSetting;
		}

		/// <summary>
		/// Save all settings to the player preferences.
		/// </summary>
		/// <param name="apply">If set to <c>true</c> applies all settings.</param>
		public static void Save(bool apply = false) {
			foreach (KeyValuePair<Type, Setting> pair in settings)
				pair.Value.Save(apply);
		}

		/// <summary>
		/// Loads all instantiated settings from the player preferences.
		/// Use this to discard changes.
		/// </summary>
		/// <param name="apply">If set to <c>true</c> applies all settings.</param>
		public static void Load(bool apply = false) {
			foreach (KeyValuePair<Type, Setting> pair in settings)
				pair.Value.Load(apply);
		}

		/// <summary>
		/// Apply all settings.
		/// </summary>
		public static void Apply() {
			foreach (KeyValuePair<Type, Setting> pair in settings)
				pair.Value.Apply();
		}
	}
}
