using System;

namespace Icarus.Logic.GameEngine 
{
	/// <summary>
	/// I am a singleton which can be used to retrieve Game Engine settings.
	/// Members are straightforward to access.
	/// </summary>
	public class GameSettings 
	{

		#region Instance Variables
		
        /// <summary>
		/// Defines the game difficulty, changes the AI, and is used by Game Calculations.    
		/// </summary>
		private int iDifficulty;
		
        /// <summary>
		/// The timescale is used to define the number of times per
		/// second that the GameEngine executes to update the world.
		/// </summary>
		private float iTimeScale;
		
        /// <summary>
		/// Defines whether cheats are on or off.
		/// </summary>
		private bool bCheatsEnabled;
		
        /// <summary>
		/// Defines how many particles are pre-allocated when a level loads.
		/// </summary>
		private uint uiMaxParticles;
		
        /// <summary>
		/// Defines the number of particles to dynamically load at a time 
		/// when the max number of particles is infinite.
		/// </summary>
		private uint uiParticleLoadRate;
		
        /// <summary>
		/// Defines how many items are pre-allocated when a level loads.
		/// </summary>
		private uint uiMaxItems;
		
        /// <summary>
		/// Defines the number of items to dynamically load at a time 
		/// when the max number of items is infinite.
		/// </summary>
		private uint uiItemLoadRate;
		
        /// <summary>
		/// Defines how many actors are pre-allocated when a level loads.
		/// </summary>
		private uint uiMaxActors;
		
        /// <summary>
		/// Defines the number of actors to dynamically load at a time 
		/// when the max number of actors is infinite.
		/// </summary>
		private uint uiActorLoadRate;
		
        /// <summary>
		/// Defines how many terrain world objects are pre-allocated when a level loads.
		/// </summary>
		private uint uiMaxTerrainObjects;
		
        /// <summary>
		/// Defines the number of terrain ojects to dynamically load at a time 
		/// when the max number of terrain objects is infinite.
		/// </summary>
		private uint uiTerrainObjectLoadRate;
		
        /// <summary>
		/// Defines how detailed the Physics calculations are.  
		/// </summary>
		private int iPhysicsDetail;
        
        /// <summary>
        /// Defines the maximum number of collision boxes in a level
        /// </summary>
        private uint uiMaxCollisionBoxes;
        
        /// <summary>
        /// The maximum internal collision rectangles a collision box can hold
        /// </summary>
        private uint uiMaxInternalRects;
        
        /// <summary>
        /// The maximum internal collision triangles a collision box can hold
        /// </summary>
        private uint uiMaxInternalTris;

        /// <summary>
        /// This defines the time between updates in milliseconds, default is 22 (45fps)
        /// </summary>
        private uint uiUpdateRate;

        /// <summary>
        /// The maximum number of stages per level
        /// </summary>
        private uint uiMaxStages;

		#endregion

		#region Singleton Stuff
        
		private static GameSettings instance = new GameSettings();
    
		/// <summary>
		/// Returns the instance of the GameSettings object
		/// </summary>
		public static GameSettings Instance 
		{
			get { return instance; }
		}

		#endregion

		#region Accessors/Modifiers
		/* ------------------- */
		/* Accessors/Modifiers */
		/* ------------------- */
        
        /// <summary>
        /// Defines the maximum number of collision boxes in a level
        /// </summary>
        public uint sv_maxCollisionBoxes
        {
            get { return this.uiMaxCollisionBoxes; }
            set { this.uiMaxCollisionBoxes = value; }
        }

        /// <summary>
        /// Defines the maximum number of internal collision rectangles
        /// a collision box can hold
        /// </summary>
        public uint sv_maxInternalRects
        {
            get { return this.uiMaxInternalRects; } 
            set { this.uiMaxInternalRects = value; }
        }

        /// <summary>
        /// Defines the maximum number of internal collision triangles
        /// a collision box can hold
        /// </summary>
        public uint sv_maxInternalTris
        {
            get { return this.uiMaxInternalTris; }
            set { this.uiMaxInternalTris = value; }
        }

		/// <summary>      
		/// A Negative difficulty should cause all enemies to freeze in place 
		/// (allowing debugging to take place).
		/// A Positive difficulty becomes more difficult with increasing values.
		/// Lowest difficulty is 0.
		/// </summary>
		public int sv_difficulty 
		{
			get { return this.iDifficulty; }
			set { this.iDifficulty = value;}
		}

		/// <summary>
		/// This sets the game's TimeScale.
		/// The timescale values can range from FLOAT_MIN to FLOAT_MAX.  
		/// Whether the full range is supported, doesn't matter.  
		/// Negatives don't matter, only the magnitude is used.   
		/// A higher number than 1.0f will result in more updates occuring per second.
		/// Numbers between 0 and 1.0, exclusive, result in fewer
		/// updates and, thus, the game moves "slower".
		/// </summary>
		public float sv_timescale 
		{
			get { return this.iTimeScale; }
			set { this.iTimeScale = value;}
		}    

		/// <summary>
		/// Activating cheats can turn on things like God Mode, which negate damage 
		/// effects to the player, as well as various other nifty debugging tools.
		/// </summary>
		public bool sv_cheats 
		{
			get { return this.bCheatsEnabled; }
			set { this.bCheatsEnabled = value;}
		}

		/// <summary>    
		/// A value of 0 means that infinite particles are allowed.
		/// In the case of infinite particles, particles will be loaded dynamically 
		/// sv_particleLoadRate at a time.
		/// Dynamic loading is much slower, but requires much less memory.
		/// </summary>
		public uint sv_maxParticles 
		{
			get { return this.uiMaxParticles; }
			set { this.uiMaxParticles = value;}
		}

		/// <summary>
		/// This defines the number of particles to dynamically load at a time 
		/// when the max number of particles is infinite.
		/// </summary>
		public uint sv_particleLoadRate 
		{
			get { return this.uiParticleLoadRate; }
			set { this.uiParticleLoadRate = value;}
		}

		/// <summary>    
		/// A value of 0 means that infinite items are allowed.
		/// In the case of infinite items, items will be loaded dynamically 
		/// sv_itemLoadRate at a time.
		/// Dynamic loading is much slower, but requires much less memory.
		/// </summary>
		public uint sv_maxItems 
		{
			get { return this.uiMaxItems; }
			set { this.uiMaxItems = value;}
		}

		/// <summary>
		/// This defines the number of items to dynamically load at a time 
		/// when the max number of items is infinite.
		/// </summary>
		public uint sv_itemLoadRate 
		{
			get { return this.uiItemLoadRate; }
			set { this.uiItemLoadRate = value;}
		}

		/// <summary>    
		/// A value of 0 means that infinite actors are allowed.
		/// In the case of infinite actors, actors will be loaded dynamically 
		/// sv_actorLoadRate at a time.
		/// Dynamic loading is much slower, but requires much less memory.
		/// </summary>
		public uint sv_maxActors 
		{
			get { return this.uiMaxActors; }
			set { this.uiMaxActors = value;}
		}

		/// <summary>
		/// This defines the number of actors to dynamically load at a time 
		/// when the max number of actors is infinite.
		/// </summary>
		public uint sv_actorLoadRate 
		{
			get { return this.uiActorLoadRate; }
			set { this.uiActorLoadRate = value;}
		}

		/// <summary>    
		/// A value of 0 means that infinite terrain objects are allowed.
		/// In the case of infinite terrain objects, terrain objects will be 
		/// loaded dynamically sv_terrainObjectLoadRate at a time.
		/// Dynamic loading is much slower, but requires much less memory.
		/// </summary>
		public uint sv_maxTerrainObjects 
		{
			get { return this.uiMaxTerrainObjects; }
			set { this.uiMaxTerrainObjects = value;}
		}

		/// <summary>
		/// This defines the number of terrain objects to dynamically load at a time 
		/// when the max number of terrain objects is infinite.
		/// </summary>
		public uint sv_TerrainObjectLoadRate 
		{
			get { return this.uiTerrainObjectLoadRate; }
			set { this.uiTerrainObjectLoadRate = value;}
		}

		/// <summary>    
		/// This may cause faster algorithms to be used in place of slower, 
		/// more precise algorithms.  
		/// This varies on Physics Engine implementation/mode.
		/// Default value is 0 (Full Detail), negative values lower
		/// detail and positive values (may) increase detail.
		/// </summary>
		public int sv_physicsDetail 
		{
			get { return this.iPhysicsDetail; }
			set { this.iPhysicsDetail = value;}
		}

        /// <summary>
        /// This stores the time between updates in milliseconds.
        /// 
        /// Note that the variable sv_timescale speeds up or slows down the
        /// game itself, this variable will affect the magnitude of vectors in
        /// the Physics Engine and alter the Physics themselves
        /// </summary>
        public uint sv_updateRate
        {
            get { return this.uiUpdateRate; }
            set { this.uiUpdateRate = value;}
        }

        /// <summary>
        /// The maximum number of stages per level
        /// </summary>
        public uint sv_maxStages
        {
            get { return this.uiMaxStages; }
            set { this.uiMaxStages = value; }
        }

		#endregion

		#region Initialization
		/* -------------- */
		/* Initialization */
		/* -------------- */
    
		/// <summary>
		/// Uses Icarus preset Game settings as defined in the variable comments.
		/// </summary>
		private GameSettings() 
		{
			this.iDifficulty = 3;
			this.iPhysicsDetail = 0;
			this.iTimeScale = 1.0f;
			this.bCheatsEnabled = false;
			this.uiParticleLoadRate = 25;
			this.uiMaxParticles = 1000;
			this.uiItemLoadRate = 25;
			this.uiMaxItems = 100;
			this.uiActorLoadRate = 25;
			this.uiMaxActors = 100;
			this.uiTerrainObjectLoadRate = 25;
			this.uiMaxTerrainObjects = 1000;
            this.uiMaxCollisionBoxes = 100;
            this.sv_maxInternalRects = 15;
            this.sv_maxInternalTris = 15;
            this.uiUpdateRate = 22; //45fps
            this.uiMaxStages = 10;
		}

		/// <summary>
		/// Load GameSettings from a File.
		/// Sets the settings to the Icarus Defaults then loads the settings from 
		/// fileName and replaces the settings specified.
		/// </summary>
		/// <param name="fileName">The fileName of settings to replace defaults.</param>
		private GameSettings(string fileName) : this() 
		{
			// TODO: Implement me    
		}
		#endregion
    
	}
}
