namespace BP
{	
	namespace UI
	{
		const float UI_DEPTH = 4.4f;
		const float UI_ELEMENT_BASESIZE = 0.01f;
		const float UI_BASE_WIDTH_RATIO = 1.0f;
		const float UI_BASE_HEIGHT_RATIO = 0.5625f;
		
		const float UI_PIXEL_WIDTH = 960.0f;
		const float UI_PIXEL_HEIGHT = 540.0f;
		
		kVec3 mousePosition;
		kVec3 lastMousePosition;
		bool mouseMoved;
		kVec3 elementScale(1.0f, 1.0f, 1.0f);
		float widthRatio = 1.0f;
		float heightRatio = 1.0f;
		float playerYaw;
		float uiYaw;
		float lastFov;
		float elementXYSize; // the x/y size value
		float elementXYScale = 1.0f; // the x/y size value
		bool isMenuOpen;
		kActor @ui;
		kActor @uiMouse;
		
		kVec3 playerPos;
		kVec3 playerForwardDir;
		kVec3 playerRightDir;
		
		Window@ activeWindow;
		array<Window@> windows;
		
		//------------------------------------------------------------------------------------------------------------------------
		bool CanOpenMainMenu()
		{
			return true;
		}
		//------------------------------------------------------------------------------------------------------------------------
		void OpenMainMenu()
		{
			//Remove when want to use ui menu stuff
			if (true)
			{
				return;
			}
			
			if (isMenuOpen)
			{
				isMenuOpen = false;
				//destroy the window (the actors and objects)
			}
			else
			{
				isMenuOpen = true;
				
				//create the spefic window (the actors and objects)
				@activeWindow = Window(0);
				windows.insertLast(@activeWindow);

				
				activeWindow.AddImage(0, 480, 270, 960, 540, 1.1f, -1, -1, array<int> = {-1,-1,-1,-1}); //BG
				
				activeWindow.AddButton(1, 160, 43, 68, 68, 1.09f, 1, 2, array<int> = {-1,-1,-1,-1}); //Abilities
				activeWindow.AddButton(2, 320, 43, 68, 68, 1.09f, 9, 10, array<int> = {-1,-1,-1,-1}); //Weapons
				activeWindow.AddButton(3, 480, 43, 68, 68, 1.09f, 7, 8, array<int> = {-1,-1,-1,-1}); //Quests
				activeWindow.AddButton(4, 640, 43, 68, 68, 1.09f, 3, 4, array<int> = {-1,-1,-1,-1}); //Map Icon
				activeWindow.AddButton(5, 800, 43, 68, 68, 1.09f, 5, 6, array<int> = {-1,-1,-1,-1}); //Options
				
				activeWindow.AddImage(6, 632, 312, 634, 448, 1.09f, 13, 13, array<int> = {-1,-1,-1,-1}); //Map
				activeWindow.AddImage(7, 632, 312, 48, 48, 1.085f, 14, 14, array<int> = {-1,-1,-1,-1}); //Map Indicator
				
				activeWindow.Open();
				
				// activeWindow.AddItem(0, Rect(0.0f, 0.0f, 1.0f, 1.0f), kVec3(UI_ELEMENT_BASESIZE, UI_ELEMENT_BASESIZE, UI_ELEMENT_BASESIZE),
					// array<int> = //stateTextureIDs
					// {
						// 0,	//Normal
						// 0,	//Selected
						// 0,	//Active
						// 0	//Disabled
					// },
					// array<int> = //navElementIDs
					// {
						// 0,	//Up
						// 0,	//Right
						// 0,	//Down
						// 0	//Left
					// }
				// );
				
				kActor @player = @BP::LocalPlayer::Actor;
				playerYaw = player.Yaw();
				uiYaw = player.Yaw() + Math::pi;
			}
		}
		//------------------------------------------------------------------------------------------------------------------------
		void Clear()
		{
			//window elements and mouse are removed via there ScriptObject (BP::UI::ScriptElement)
			windows.resize(0);
			@activeWindow = null;
			@uiMouse = null;
		}
		//------------------------------------------------------------------------------------------------------------------------
		void OnStart()
		{
			Clear();
			
			//Setup UI
			if (Sys.VideoWidth() > Sys.VideoHeight())
			{
				widthRatio = 1.0f;
				heightRatio = float(Sys.VideoHeight()) / Sys.VideoWidth();
			}
			else
			{
				widthRatio = float(Sys.VideoWidth()) / Sys.VideoHeight();
				heightRatio = 1.0f;
			}
			elementScale = kVec3(UI_BASE_WIDTH_RATIO / widthRatio, 1.0f, UI_BASE_HEIGHT_RATIO / heightRatio);
			
			// @ui = BP::Spawn::Actor(kActor_UIElement, Math::vecZero);
			@uiMouse = BP::Spawn::Actor(kActor_UIElement, Math::vecZero);
			uiMouse.RenderMeshComponent().AltTexture() = 0;
			uiMouse.Flags() |= AF_HIDDEN;
		}
		//------------------------------------------------------------------------------------------------------------------------
		void OnDeserializeStart()
		{
			Clear();
		}
		//------------------------------------------------------------------------------------------------------------------------
		void OnTick()
		{
			//if ui is not active then return
			if (!isMenuOpen)
			{
				return;
			}

			//Check Fov change
			float fov = BP::Game::GetFOV();
			if (lastFov != fov)
			{
				lastFov = fov;
				float fovDif = BP::Game::GetFOV() - 90.0f;
				elementXYScale = Math::Pow(1.017974f, Math::Fabs(fovDif));
				if (fovDif < 0)
				{
					elementXYScale = 1 / elementXYScale;
				}
				elementXYSize = UI_DEPTH * elementXYScale;
				
				elementScale = kVec3(UI_BASE_WIDTH_RATIO / widthRatio, 1.0f, UI_BASE_HEIGHT_RATIO / heightRatio);
				elementScale *= elementXYScale;
			}
			
			//get mouse position
			mousePosition.x = float(Sys.Mouse_X()) / Sys.VideoWidth();
			mousePosition.z = float(Sys.Mouse_Y()) / Sys.VideoHeight();
			
			//check if mouse is moving
			mouseMoved = false;
			if (lastMousePosition.x != mousePosition.x || lastMousePosition.z != mousePosition.z)
			{
				lastMousePosition = mousePosition;
				mouseMoved = true;
			}
			
				
			kActor @player = @BP::LocalPlayer::Actor;
			
			player.Yaw() = playerYaw;
			player.Pitch() = 0;
			player.Roll() = 0;
			
			float pHeight = ((LocalPlayer.Actor().PlayerFlags() & PF_CRAWLING) != 0) ? 50.0f : 100.0f;
			playerPos = player.Origin() + kVec3(0, 0, pHeight);
			playerForwardDir = BP::Actor::Forward(player);
			playerRightDir = BP::Actor::Right(player);
			
			
			float mouseDepth = UI_DEPTH * elementXYScale;
			
			uiMouse.Origin() = playerPos + playerForwardDir * (4.4 * heightRatio);
			uiMouse.Origin() += (playerRightDir * (mouseDepth * 2.0f)) * mousePosition.x - (playerRightDir * mouseDepth);
			uiMouse.Origin().z += ((mouseDepth * 2.0f) * heightRatio) * (1.0f - mousePosition.z) - (mouseDepth * heightRatio);

			uiMouse.Scale() = kVec3(0.0004f, 0.01f, 0.0004f) * elementScale;
			uiMouse.Yaw() = uiYaw;
			
			int windowsLength = int(windows.length());
			for (int i = 0; i < windowsLength; i++)
			{
				windows[i].OnTick();
			}
			
			if (@activeWindow != null)
			{
				activeWindow.OnTickActive();
			}
		}
		//------------------------------------------------------------------------------------------------------------------------
	}
}
