using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Bridge;
using Bridge.Html5;
using Bridge.WebGL;
using Mox.Bridge.Renderer;
using Mox.Shared;

namespace Mox.Bridge
{
	internal class Program : ProgramBase
	{
		public static void Main()
		{
			IOHelper.GetText = async _sPath => Encoding.UTF8.GetString(await AsyncAjax.Get(_sPath));
			IOHelper.GetBytes = async _sPath => await AsyncAjax.Get(_sPath);
			var program = new Program();
			program.Run();
		}

		private async void Run()
		{
			var canvas = Document.GetElementById("game").As<HTMLCanvasElement>();
			canvas.Width = c_iClientWidth;
			canvas.Height = c_iClientHeight;
			Renderer = new WebGLRenderer(canvas);

			Document.AddEventListener(EventType.KeyPress, HandleKeyPress);
			Document.AddEventListener(EventType.MouseDown, HandleMouseDown);
			Document.AddEventListener(EventType.MouseMove, HandleMouseMove);
			Document.AddEventListener(EventType.MouseUp, HandleMouseUp);

			await GameLoop.Init();
			Init();

			Window.RequestAnimationFrame(LoopOnce);
		}

		public override async Task RegisterSound(string _sSoundId, string _sPath)
		{
			m_dSounds[_sSoundId] = await Sound.Create(_sPath);
		}

		private void HandleMouseDown(Event _arg)
		{
			if (_arg is MouseEvent evt)
			{
				OnMouseDown(evt.ClientX, evt.ClientY);
			}
		}

		private void HandleMouseMove(Event _arg)
		{
			if (_arg is MouseEvent evt)
			{
				OnMouseMoved(evt.ClientX, evt.ClientY);
			}
		}

		private void HandleMouseUp(Event _arg)
		{
			if (_arg is MouseEvent evt)
			{
				OnMouseUp(evt.ClientX, evt.ClientY);
			}
		}

		private void LoopOnce(double _dTime)
		{
			var delta = (_dTime - m_dLastTime) / 1000;
			m_dLastTime = _dTime;
			Update(delta);
			Window.RequestAnimationFrame(LoopOnce);
		}

		private void HandleKeyPress(Event _arg)
		{
			if (_arg is KeyboardEvent evt && s_dKeyCodes.TryGetValue(evt.KeyCode, out var eKey))
			{
				GameLoop.OnKeyPressed(eKey);
			}
		}

		public override void ShowMessage(string _sMessage)
		{
			Global.Alert(_sMessage);
		}

		public override bool GetData(string _sKey, out string _sData)
		{
			var o = Window.LocalStorage[_sKey];

			if (o != null)
			{
				_sData = o as string;

				return true;
			}

			_sData = null;

			return false;
		}

		public override void SetData(string _sKey, string _sData)
		{
			if (_sData == null)
			{
				Window.LocalStorage.RemoveItem(_sKey);
			}
			else
			{
				Window.LocalStorage.SetItem(_sKey, _sData);
			}
		}

		private double m_dLastTime;
	}
}
