using System;
using System.Threading;

using Icarus.Logic.GameEngine;
using Icarus.Scripting;

namespace Icarus.Runner
{
	/// <summary>
	/// This is a the main Icarus Runner class.
	/// </summary>
	public sealed class IcarusMain
	{
		private IcarusMain() { }

		private static Icarus.Renderer.D3DGameWindow window;
		private static int framerate = 60;
		private static bool showConsole = true;

		/// <summary>
		/// This function is here because the compiler is too smart for its own good. If we don't use anything from an assembly, it won't even load it. So we have to do something here to be able to use the assemblies through scripting.
		/// </summary>
		private static void dummyfunc() 
		{
			object o = null;

			//Physics:
			o = new Icarus.Logic.Physics.Point();
		}

		private static void bindButtonToAction(string action, string button) 
		{
			string mouse = "Mouse ";
			string keyboard = "Keyboard ";
			string joystick = "Joystick ";

			if (button.StartsWith(mouse)) 
			{
				Input.InputEngine.Instance.bindMouseButton(button.Substring(mouse.Length), action);
			} 
			else if (button.StartsWith(keyboard)) 
			{
				Input.InputEngine.Instance.bindKey(button.Substring(keyboard.Length), action);
			} 
			else if (button.StartsWith(joystick)) 
			{
				Input.InputEngine.Instance.bindJoystickButton(button.Substring(joystick.Length), action);
			}
		}

		private static void bindButtonActions(string action, string buttons) 
		{
			string[] buttonlist = buttons.Split(';');

			foreach (string button in buttonlist) 
			{
				bindButtonToAction(action, button.Trim());
			}
		}

		private static void processConfiguration() 
		{
			//Check to see if the config exists
			Icarus.Resources.ConfigParser cp = null;

			try 
			{
				cp = new Icarus.Resources.ConfigParser("config.icfg");
			}
			catch (Exception) 
			{
				//Too bad...
				return;
			}

			Icarus.Resources.ResourceManager.Instance.BasePath = cp["Load_Asset_Path"];
			framerate = Int32.Parse(cp["TargetFrameRate"]);
			Icarus.Renderer.Direct3DSettings.Instance.AnimationDelay = Int32.Parse(cp["AnimationDelay"]);
			Icarus.Renderer.Direct3DSettings.Instance.RenderCollisionBoxes = Boolean.Parse(cp["RenderCollisionBoxes"]);
			Icarus.Renderer.Direct3DSettings.Instance.ScrollMargin = Int32.Parse(cp["ScrollMargin"]);

			bindButtonActions("left", cp["ActionLeft"]);
			bindButtonActions("right", cp["ActionRight"]);
			bindButtonActions("up", cp["ActionUp"]);
			bindButtonActions("down", cp["ActionDown"]);
			bindButtonActions("shoot", cp["ActionShoot"]);

			TuxHunter.TuxHunterSettings.Instance.ShowSnappy = Boolean.Parse(cp["ShowSnappy"]);

			IcarusMain.showConsole = Boolean.Parse(cp["ShowConsole"]);
		}

        /// <summary>
        /// This executes the Icarus Game Engine.
        /// </summary>
        /// <param name="args">Command Line Parameters</param>
		[STAThread]
		public static void Main(string[] args) {
			dummyfunc();

			processConfiguration();

			Icarus.Graphics.Animation.AnimationFactory.setInstance(new Icarus.Renderer.Animation.D3DAnimationFactory());

			ScriptingConsole sc = null;
			if (IcarusMain.showConsole)
			{
				//Make a scripting console:
				sc = new ScriptingConsole();
				Console.SetError(sc.ConsoleWriter);
				Console.SetOut(sc.ConsoleWriter);
			}

			//Make a window:
			window = new Icarus.Renderer.D3DGameWindow("Tux Hunter", true);
			window.FrameRate = framerate;
			window.RenderCallback = new Icarus.Renderer.RenderFunction(GameEngine.Instance.RenderCurrentState);

			//Initialize various components of the engine:
			Input.InputEngine.Instance.Initialize(window);
			Icarus.SoundEngine.SoundEngine.Instance.Initialize(window);

			//Start the game engine off in the Splash Screen State:
			//NOTE: This MUST be done after the game window has been initialized.
			GameEngine.Instance.PushState(new TuxHunter.GameStates.SplashScreenState());

			//Start up the game engine:
            Thread gameEngine_thread = new Thread(new ThreadStart(GameEngine.Instance.RunThread));
			GameEngine.Instance.Play();
            gameEngine_thread.Start();

			//Run:
			if (IcarusMain.showConsole) { sc.Show(); }
			System.Windows.Forms.Application.Run(window);

            Icarus.SoundEngine.SoundEngine.Instance.StopMusic(); //TODO: Move to whichever place starts music.
			GameEngine.Instance.Stop();
            gameEngine_thread.Join();
		}
	}
}
