using Cryville.Common.ComponentModel;
using System.ComponentModel;
using UnityEngine;
using RangeAttribute = Cryville.Common.ComponentModel.RangeAttribute;

namespace Cryville.Crtr {
	public class Settings {
		[Category("graphics")]
		[LogarithmicScale][Step(0.5f)][Precision(1e-2)]
		public float BackwardClippingDistance {
			get {
				return PlayerPrefs.GetFloat("BackwardClippingDistance", 0.2f);
			}
			set {
				PlayerPrefs.SetFloat("BackwardClippingDistance", value);
			}
		}

		static readonly Settings _default = new Settings();
		[Browsable(false)]
		public static Settings Default {
			get {
				return _default;
			}
		}

		[Category("gameplay")]
		public bool DisableGC {
			get {
				return PlayerPrefs.GetInt("DisableGC", 1) == 1;
			}
			set {
				PlayerPrefs.SetInt("DisableGC", value ? 1 : 0);
			}
		}

		[Browsable(false)]
		[Category("data")]
		[Description("The directory where the game files are stored.")]
		public string GameDataPath {
			get {
				string dataPath = Application.persistentDataPath;
#if UNITY_ANDROID && !UNITY_EDITOR
				dataPath = "/storage/emulated/0/data/crtr";
#endif
				return PlayerPrefs.GetString("GameDataPath", dataPath);
			}
			set {
				PlayerPrefs.SetString("GameDataPath", value);
			}
		}

		[Browsable(false)]
		public string LastRunVersion {
			get {
				return PlayerPrefs.GetString("LastRunVersion", "0.0");
			}
			set {
				PlayerPrefs.SetString("LastRunVersion", value);
			}
		}

		[Browsable(false)]
		[Category("data")]
		[Description("The chart file to load.")]
		public string LoadChart {
			get {
				return PlayerPrefs.GetString("LoadChart", "");
			}
			set {
				PlayerPrefs.SetString("LoadChart", value);
			}
		}

		[Browsable(false)]
		[Category("data")]
		[Description("The ruleset file to load.")]
		public string LoadRuleset {
			get {
				return PlayerPrefs.GetString("LoadRuleset", "");
			}
			set {
				PlayerPrefs.SetString("LoadRuleset", value);
			}
		}

		[Browsable(false)]
		[Category("data")]
		[Description("The ruleset config file to load.")]
		public string LoadRulesetConfig {
			get {
				return PlayerPrefs.GetString("LoadRulesetConfig", "");
			}
			set {
				PlayerPrefs.SetString("LoadRulesetConfig", value);
			}
		}

		[Browsable(false)]
		[Category("data")]
		[Description("The skin file to load.")]
		public string LoadSkin {
			get {
				return PlayerPrefs.GetString("LoadSkin", "");
			}
			set {
				PlayerPrefs.SetString("LoadSkin", value);
			}
		}

		[Category("graphics")]
		[LogarithmicScale][Step(0.5f)][Precision(1e-1)]
		public float RenderDistance {
			get {
				return PlayerPrefs.GetFloat("RenderDistance", 6);
			}
			set {
				PlayerPrefs.SetFloat("RenderDistance", value);
			}
		}

		[Category("graphics")]
		[Description("The span before the renderer fetches the object data again. Smaller value generates more detailed objects while increasing CPU load. Leave 0 to let the game decides the value automatically.")]
		[Range(0, 0.1f)][Precision(1e-3)]
		public float RenderStep {
			get {
				return PlayerPrefs.GetFloat("RenderStep", 0f);
			}
			set {
				PlayerPrefs.SetFloat("RenderStep", value);
			}
		}

		[Category("gameplay")]
		[LogarithmicScale][Step(0.5f)][Precision(1e-1)]
		public float ScrollVelocity {
			get {
				return PlayerPrefs.GetFloat("ScrollVelocity", 1);
			}
			set {
				PlayerPrefs.SetFloat("ScrollVelocity", value);
			}
		}

		[Category("gameplay")]
		[Step(0.04f)][Precision(1e-3)]
		public float SoundOffset {
			get {
				return PlayerPrefs.GetFloat("SoundOffset", 0);
			}
			set {
				PlayerPrefs.SetFloat("SoundOffset", value);
			}
		}

		[Browsable(false)]
		[Category("gameplay")]
		[Description("(Not implemented yet)")]
		public float StartOffset {
			get {
				return PlayerPrefs.GetFloat("StartOffset", 0);
			}
			set {
				PlayerPrefs.SetFloat("StartOffset", value);
			}
		}

		[Category("graphics")]
		[LogarithmicScale][Range(15, 1024)][Step(0.5f)]
		public int TargetFrameRate {
			get {
				return PlayerPrefs.GetInt("TargetFrameRate", 60);
			}
			set {
				PlayerPrefs.SetInt("TargetFrameRate", value);
			}
		}

		[Category("graphics")]
		public bool VSync {
			get {
				return PlayerPrefs.GetInt("VSync", 0) == 1;
			}
			set {
				PlayerPrefs.SetInt("VSync", value ? 1 : 0);
			}
		}

		public void Save() { PlayerPrefs.Save(); }
		public void Reset() { PlayerPrefs.DeleteAll(); }
	}
}