// Mouse Handler.
// Worthless Bums 2012.


function pickCursorObjects ()
{//echo("pickCursorObjects()");
	%mousePosition = sceneWindow2D.getMousePosition();
	%pointObjects = levelSceneGraph.pickPoint(getWord(%mousePosition, 0), getWord(%mousePosition, 1));
	// Only look at the first dozen objects. Arbitrary - we don't have that many objects at any one point anyway.
	// NOTE: This assumption may come back to bite me.
	for (%i = 0; %i < 12; %i++)
	{
		// Workaround to determine if words are valid.
		%word = getWord(%pointObjects, %i);
		%word2 = getWord(%pointObjects, %i + 1);
		if (%word != %word2)
		{
			%objectID = %word;
		}
	}
	//echo(%pointObjects);	// For testing purposes only!
	return false;
}
function getMouseTileIndices ()
{//echo("getMouseTileIndices()");
	%mousePosition = sceneWindow2D.getMousePosition();
	%xPos = getWord(%mousePosition, 0);
	%yPos = getWord(%mousePosition, 1);
	//%yPos -= 1;	// Adjust mouse position for shifted tiles!
	%xIndex = mFloor(%xPos / 4);
	%yIndex = mFloor(%yPos / 4);
	return %xIndex SPC %yIndex;
}
function mouseOverSquadMember ()
{//echo("mouseOverSquadMember()");
	%mouseIndices = getMouseTileIndices();
	%mouseX = getWord(%mouseIndices, 0);
	%mouseY = getWord(%mouseIndices, 1);
	if ($leaderPersist						&&
		$playerSquad[0].xIndex == %mouseX	&&
		$playerSquad[0].yIndex == %mouseY)
	{
		return 0;
	}
	else if ($scoutPersist						&&
			 $playerSquad[1].xIndex == %mouseX	&&
			 $playerSquad[1].yIndex == %mouseY)
	{
		return 1;
	}
	else if ($grenadierPersist					&&
			 $playerSquad[2].xIndex == %mouseX	&&
			 $playerSquad[2].yIndex == %mouseY)
	{
		return 2;
	}
	else if ($supportPersist					&&
			 $playerSquad[3].xIndex == %mouseX	&&
			 $playerSquad[3].yIndex == %mouseY)
	{
		return 3;
	}
	else
	{
		return -1;
	}
}
function mouseOverMonster ()
{//echo("mouseOverMonster()");
	%mouseIndices = getMouseTileIndices();
	%mouseX = getWord(%mouseIndices, 0);
	%mouseY = getWord(%mouseIndices, 1);
	for (%i = 0; %i < $monsterList.getCount(); %i++)
	{
		%monster = $monsterList.getObject(%i);
		if (%monster.xIndex == %mouseX	&&
			%monster.yIndex == %mouseY)
		{
			// Make sure this monster is revealed to the player!
			if ($fogOfWar.isClear(%mouseX, %mouseY))
			{
				return %i;
			}
		}
	}
	return -1;
}
function GuiMouseEventCtrl::onMouseDown (%this, %mod, %worldPos, %mouseClicks)
{//echo("GuiMouseEventCtrl::onMouseDown()");
	$LastTimeSinceMouseEvent = getScriptTimer();
	// Check action flag.
	if ($currentCharacterActionFlag)
	{
		return;
	}
	
	// Fire if clicked anywhere after targeting a monster!
	if ($fireControlInitiated)
	{
		firePrimary(0);
		return;
	}
	
	// If there's a pending autoswitch squad member event, cancel it.
	//cancelAutoSwitchEvents();
	
	// Clear target indicators.
	clearTargetIndicators(false);
	// Clear fire control.
	clearFireControl();
	
	// Check if the player has clicked on a squad member.
	%mouseSquadMember = mouseOverSquadMember();
	if (%mouseSquadMember != -1)
	{
		// Select squad member.
		selectSquadMember(%mouseSquadMember);
		
		return;
	}
	
	// Check if the player has clicked on a monster.
	%mouseMonster = mouseOverMonster();
	if (%mouseMonster != -1)
	{//echo("inWeaponRange(%mouseMonster) =" SPC inWeaponRange(%mouseMonster));
		// Make sure the monster is within weapon range and the squad member is facing in the proper direction!
		if (inWeaponRange(%mouseMonster))
		{//echo("inWeaponRange(%mouseMonster) =" SPC inWeaponRange(%mouseMonster));
			firePrimary(0);
			return;
		}
	}
	
	// This moves in one tile cardinal directions only!
	// Grab mouse position.
	%mousePosition = sceneWindow2D.getMousePosition();
	%xPos1 = getWord(%mousePosition, 0);
	%yPos1 = getWord(%mousePosition, 1);
	// Grab active character position.
	%unitPosition = $playerSquad[$activeCharacter].getPosition();
	%xPos2 = getWord(%unitPosition, 0);
	%yPos2 = getWord(%unitPosition, 1);
	// Need to shift position to compensate for bounding box!
	//%padding = 2;
	//%xPos2 += %padding;
	//%yPos2 += %padding;
	
	// Disregard click if it's too close to the unit!
	%distance = VectorDist(%mousePosition, %unitPosition);
	if (%distance < 2.0)
	{
		return;
	}
	
	// Get direction relative from unit to cursor position.
	%direction = getDirectionFromCursor(%xPos1, %yPos1, %xPos2, %yPos2);
	
	// Move in that direction.
	moveCharacter($activeCharacter, %direction);
}
function GuiMouseEventCtrl::onRightMouseDown (%this, %mod, %worldPos, %mouseClicks)
{//echo("GuiMouseEventCtrl::onRightMouseDown()");
//echo("mouse right down position:" SPC sceneWindow2D.getMousePosition());
	$LastTimeSinceMouseEvent = getScriptTimer();
	if ($currentCharacterActionFlag)
	{
		return;
	}
	
	clearTargetIndicators(false);
	clearFireControl();
	
	// Check if the player has clicked on a squad member.
	%mouseSquadMember = mouseOverSquadMember();
	if (%mouseSquadMember != -1)
	{
		selectSquadMember(%mouseSquadMember);
		return;
	}
	
	// Grab mouse position.
	%mousePosition = sceneWindow2D.getMousePosition();
	%xPos1 = getWord(%mousePosition, 0);
	%yPos1 = getWord(%mousePosition, 1);
	// Grab active character position.
	%unitPosition = $playerSquad[$activeCharacter].getPosition();
	%xPos2 = getWord(%unitPosition, 0);
	%yPos2 = getWord(%unitPosition, 1);
	// Disregard click if it's too close to the unit!
	%distance = VectorDist(%mousePosition, %unitPosition);
	if (%distance < 2.0)
	{
		return;
	}
	
	// Get direction relative from unit to cursor position.
	%direction = getDirectionFromCursor(%xPos1, %yPos1, %xPos2, %yPos2);
	
	// Move in that direction.
	switch (%direction)
	{
		case $southDirection:	faceUp(1);
		case $northDirection:	faceDown(1);
		case $eastDirection: 	faceRight(1);
		case $westDirection: 	faceLeft(1);
	}
}

// Returns the direction between the two specified points.
// NOTE: This function assumes at least one direction of cardinal alignment - not the responsibility of this function to ensure!
function getDirectionFromCursor (%xPos1, %yPos1, %xPos2, %yPos2)
{//echo("getDirectionFromCursor()");
	// Center first coordinate around (0, 0).
	%x = %xPos1 - %xPos2;
	%y = %yPos1 - %yPos2;
	
	// Split into quadrants.
	// Quadrant 1.
	if (%x >= 0	&&
		%y <= 0)
	{
		if (%x > mAbs(%y))
		{
			return $eastDirection;
		}
		else
		{
			return $northDirection;
		}
	}
	// Quadrant 2.
	else if (%x <= 0	&&
			 %y <= 0)
	{
		if (mAbs(%x) > mAbs(%y))
		{
			return $westDirection;
		}
		else
		{
			return $northDirection;
		}
	}
	// Quadrant 3.
	else if (%x <= 0	&&
			 %y >= 0)
	{
		if (mAbs(%x) > %y)
		{
			return $westDirection;
		}
		else
		{
			return $southDirection;
		}
	}
	// Quadrant 4.
	else if (%x >= 0	&&
			 %y >= 0)
	{
		if (%x > %y)
		{
			return $eastDirection;
		}
		else
		{
			return $southDirection;
		}
	}
	//return $northDirection;		// This should never happen, but we don't want to pass function moveCharacter() a bad direction!
}
function freeTargetIndicator ()
{//echo("freeTargetIndicator()");
	$targetIndicatorFree = true;
}
function checkMouseEvents ()
{//echo("checkMouseEvents()");echo("$LastTimeSinceMouseEvent =" SPC $LastTimeSinceMouseEvent);echo("getScriptTimer() =" SPC getScriptTimer());echo("$MouseFadeTime =" SPC $MouseFadeTime);
	/*%mousePosition = sceneWindow2D.getMousePosition();//$CurrentGuiCursor
	%xPos1 = getWord(%mousePosition, 0);
	%yPos1 = getWord(%mousePosition, 1);
	%mouseIndices = getTileIndicesFromCursor(%xPos1, %yPos1);
	$MouseCurrentWorldPosition = %mouseIndices;*/
	if ($AlwaysShowCursor)
	{
		Canvas.showCursor();
		return;
	}
	if (getScriptTimer() - $LastTimeSinceMouseEvent > $MouseFadeTime)
	{
		//Canvas.hideCursor();		// Disabled for now since it doesn't reappear!
	}
	if (!isEventPending($MouseCheckEvent))
	{
		$LastKnownMousePosition = Canvas.getCursorPos();
		$MouseCheckEvent = schedule(1000, 0, "checkMouseEvents");
	}
	// Always show cursor on gui events!
	if ($mainMenuPushed			||
		$squadInfoGuiPushed		||
		$promotionGuiPushed		||
		$endLevelScreenPushed	||
		$deathScreenPushed		||
		$survivorScreenPushed	||
		$guiInProgress			||
		$consoleToggledOn)
	{//echo("SHOWING CURSOR!");
		Canvas.showCursor();
	}
}
function checkMousePosition ()
{//echo("checkMousePosition()");
return;	// Disabled for now! This is now handled by GuiCanvas::checkCursor(), I think! - T2D v3.0. 
	if ($LastKnownMousePosition != Canvas.getCursorPos())
	{
		$LastKnownMousePosition = Canvas.getCursorPos();
		$LastTimeSinceMouseEvent = getScriptTimer();
		checkMouseEvents();
		handleMouseMovement();	// For more responsive tile/cursor for mouse movement. Disable if this bottlenecks CPU on some machines!
	}
	schedule(50, 0, "checkMousePosition");
}
// Inventory Tab Gui is on top so pass calls down to sceneWindow2D!
function GuiControl::onMouseMove (%this, %mod, %worldPos, %mouseClicks)
{//echo("GuiControl::onMouseMove()");echo("%worldPos =" SPC %worldPos);//echo("GuiControl.name =" SPC GuiControl.name);
	$CursorGuiControl = %this;
	if ($MouseLastWorldPosition != %worldPos)	// Detect cursor position change.
	{//echo("mouse move detected!");
		$MouseLastWorldPosition = %worldPos;
		$LastTimeSinceMouseEvent = getScriptTimer();
		handleMouseMovement();
	}
}
function sceneWindow2D::onMouseMove (%this, %mod, %worldPos, %mouseClicks)
{//echo("sceneWindow2D::onMouseMove()");
	if ($MouseLastWorldPosition != %worldPos)	// Detect cursor position change.
	{//echo("mouse move detected!");
		$MouseLastWorldPosition = %worldPos;
		$LastTimeSinceMouseEvent = getScriptTimer();
		handleMouseMovement();
	}
}
function toggleMoveIndicators ()
{//echo("toggleMoveIndicators()");
	$ignoreMouseFieldControl = !$ignoreMouseFieldControl;
}
// Handles mouse movement.
function handleMouseMovement ()
{//echo("handleMouseMovement()");//echo("sceneWindow2D.getIsCameraMoving() =" SPC sceneWindow2D.getIsCameraMoving());
//return;		// Uncomment for trailer footage!
	/*if (!$Game::AlwaysShowMoveIndicator)
	{
		clearTargetIndicators(false);
		if (isObject($mouseMoveIndicator))
		{
			$mouseMoveIndicator.safeDelete();
		}
		return;
	}*/
	
	// Doesn't work because cursor position doesn't change when the cursor is hidden!
	/*echo($LastWindowPoint NL sceneWindow2D.getWindowPoint(sceneWindow2D.getmouseposition()));
	if (sceneWindow2D.getWindowPoint(sceneWindow2D.getmouseposition()) !$= $LastWindowPoint)
	{//echo("SHOW CURSOR!");
		showCursor();
		$LastWindowPoint = sceneWindow2D.getWindowPoint(sceneWindow2D.getmouseposition());
	}*/
	
	// Uncomment below of mouse cursor debugging!
	/*updateEventText("GuiControl::onMouseMove()");
	// Grab mouse position.
	%mousePosition = sceneWindow2D.getMousePosition();
	//echo("%mousePosition =" SPC %mousePosition);
	%xPos1 = getWord(%mousePosition, 0);
	%yPos1 = getWord(%mousePosition, 1);
	// Mouse indices possibly used below.
	%mouseIndices = getTileIndicesFromCursor(%xPos1, %yPos1);//getIndicesFromTilePosition(%xPos1, %yPos1);
	echo("%mouseIndices =" SPC %mouseIndices);
	if ($lastMouseIndices !$= %mouseIndices)
	{
	updateEventText("%mousePosition =" SPC %mousePosition);
	updateEventText("%mouseIndices =" SPC %mouseIndices);
	$lastMouseIndices = %mouseIndices;
	}*/
	
	if (!isObject($playerSquad[$activeCharacter]))
	{
		return;
	}
	// Only execute if it's the player's turn and the game isn't paused!
	if (!$monsterTurnOngoing			&&
		!$currentCharacterActionFlag	&&
		$timescale > 0					&&
		!sceneWindow2D.getIsCameraMoving())
	{
		// Grab mouse position.
		%mousePosition = sceneWindow2D.getMousePosition();
		//echo("%mousePosition =" SPC %mousePosition);
		%xPos1 = getWord(%mousePosition, 0);
		%yPos1 = getWord(%mousePosition, 1);
		// Mouse indices possibly used below.
		%mouseIndices = getTileIndicesFromCursor(%xPos1, %yPos1);
		%mouseXIndex = mRound(getWord(%mouseIndices, 0));
		%mouseYIndex = mRound(getWord(%mouseIndices, 1));
		if ($LastMouseXIndex == %mouseXIndex	&&
			$LastMouseYIndex == %mouseYIndex)
		{
			return;
		}//echo($LastMouseXIndex SPC $LastMouseYIndex);
		$LastMouseXIndex = %mouseXIndex;
		$LastMouseYIndex = %mouseYIndex;
		// Grab active character position.
		%unitPosition = $playerSquad[$activeCharacter].getPosition();
		%xPos2 = getWord(%unitPosition, 0);
		%yPos2 = getWord(%unitPosition, 1);
		
		// Get direction relative from unit to cursor position.
		%direction = getDirectionFromCursor(%xPos1, %yPos1, %xPos2, %yPos2);
		
		// Highlight appropriate tile.
		%xPos = -9999;
		%yPos = -9999;
		%padding = 0.5;	// For shifted sprite positions on tiles.
		switch (%direction)
		{
			case $northDirection:
				%xPos = %xPos2;
				%yPos = %yPos2 - (4 - %padding);
				
			case $southDirection:
				%xPos = %xPos2;
				%yPos = %yPos2 + (4 + %padding);
				
			case $eastDirection:
				%xPos = %xPos2 + 4;
				%yPos = %yPos2 + %padding;
				
			case $westDirection:
				%xPos = %xPos2 - 4;
				%yPos = %yPos2 + %padding;
		}
		
		// Check if the cursor is on a squad member.
		%indices = getIndicesFromTilePosition(%xPos1, %yPos1);
		%xIndex = mRound(getWord(%indices, 0));
		%yIndex = mRound(getWord(%indices, 1));
		%mouseSquadMemberIndex = mouseOverSquadMember();
		// Set indicator position to this squad member's position.
		if (%mouseSquadMemberIndex != -1)
		{//echo("%mouseSquadMemberIndex =" SPC %mouseSquadMemberIndex);
			%xPos = getWord($playerSquad[%mouseSquadMemberIndex].position, 0);
			%yPos = getWord($playerSquad[%mouseSquadMemberIndex].position, 1);
			if ($playerSquad[%mouseSquadMemberIndex].xIndex == $squadMemberTargetXIndex	&&
				$playerSquad[%mouseSquadMemberIndex].yIndex == $squadMemberTargetYIndex)
			{
				clearTargetIndicators(false);
				$squadMemberTargetXIndex = -1;
				$squadMemberTargetYIndex = -1;
			}
			else
			{//echo("setting new target indicators!");
				if ($targetIndicatorFree)
				{
					clearTargetIndicators(false);
					setTargetIndicators(%mouseSquadMemberIndex);
					$squadMemberTargetXIndex = $playerSquad[%mouseSquadMemberIndex].xIndex;
					$squadMemberTargetYIndex = $playerSquad[%mouseSquadMemberIndex].yIndex;
				}
			}
			createUnitTooltip($playerSquad[%mouseSquadMemberIndex]);
			return;
		}
		else
		{
			clearTargetIndicators(false);
			$squadMemberTargetXIndex = -1;
			$squadMemberTargetYIndex = -1;
			$targetIndicatorFree = true;
			deleteUnitTooltip();
		}
		
		// Check if the cursor is on a monster.
		%mouseMonsterIndex = mouseOverMonster();
		// Set indicator position to this squad member's position.
		if (%mouseMonsterIndex != -1)
		{
			%monster = $monsterList.getObject(%mouseMonsterIndex);
			%xPos = getWord(%monster.position, 0);
			%yPos = getWord(%monster.position, 1);
			// Check for new indicator position(s)!
			if ($enemyTargetXIndex == %monster.xIndex	&&
				$enemyTargetYIndex == %monster.yIndex)
			{
				// Nothing here yet!
			}
			else
			{
				// Lay down attack indicators!
				if (isObject($enemyTargetIndicators))
				{
					for (%i = 0; %i < $enemyTargetIndicators.getCount(); %i++)
					{
						($enemyTargetIndicators.getObject(%i)).safeDelete();
					}
				}
				else
				{
					$enemyTargetIndicators = new SimSet();
				}
				%effectiveRange = 1;
				if (%monster.canRange)
				{
					%effectiveRange = mRound(%monster.range / 4);
				}
				%xIndex = %monster.xIndex;
				%yIndex = %monster.yIndex;
				$enemyTargetXIndex = %xIndex;
				$enemyTargetYIndex = %yIndex;
				for (%i = 1; %i <= %effectiveRange; %i++)
				{
					switch (%monster.facing)
					{
						case $northDirection:	%yIndex--;
						case $southDirection:	%yIndex++;
						case $eastDirection:	%xIndex++;
						case $westDirection:	%xIndex--;
					}
					%targetIndicatorAnimation = createTargetIndicatorAnimation();
					%targetIndicatorAnimation.xIndex = %xIndex;
					%targetIndicatorAnimation.yIndex = %yIndex;
					scheduleObjectMove(%targetIndicatorAnimation, getTileShiftedPositionFromIndices(%xIndex, %yIndex), 0);
					$enemyTargetIndicators.add(%targetIndicatorAnimation);
				}
				
				// Lay down movement indicators!
				// Nothing here yet!
			}
			
			// Set tooltip popup here!
			createUnitTooltip(%monster);
		}
		else
		{
			if (isObject($enemyTargetIndicators))
			{
				for (%i = 0; %i < $enemyTargetIndicators.getCount(); %i++)
				{
					($enemyTargetIndicators.getObject(%i)).safeDelete();
				}
			}
			else
			{
				$enemyTargetIndicators = new SimSet();
			}
			$enemyTargetXIndex = -1;
			$enemyTargetYIndex = -1;
		}
		
		// Check if we have an existing indicator.
		if (isObject($mouseMoveIndicator))
		{
			// Don't replace indicator if the current one is already on the same position!
			if ($mouseMoveIndicator.xIndex == %mouseXIndex	&&
				 $mouseMoveIndicator.yIndex == %mouseYIndex)
			{
				return;
			}
			else
			{
				$mouseMoveIndicator.safeDelete();
			}
		}
		
		// Need different indicators for:
		//	1) Free space (movable).
		//	2) Friendly occupied space (swappable).
		//	3) Object in space (e.g. crate).
		//	4) Hostile in space (e.g. Brute).
		//	5) Off limits (might be the same as #3?).
		// Create the indicator.
		// Get only adjacent tile status!
		switch (%direction)
		{
			case $northDirection:
				%mouseIndexX = $playerSquad[$activeCharacter].xIndex;
				%mouseIndexY = $playerSquad[$activeCharacter].yIndex - 1;
			
			case $southDirection:
				%mouseIndexX = $playerSquad[$activeCharacter].xIndex;
				%mouseIndexY = $playerSquad[$activeCharacter].yIndex + 1;
			
			case $eastDirection:
				%mouseIndexX = $playerSquad[$activeCharacter].xIndex + 1;
				%mouseIndexY = $playerSquad[$activeCharacter].yIndex;
			
			case $westDirection:
				%mouseIndexX = $playerSquad[$activeCharacter].xIndex - 1;
				%mouseIndexY = $playerSquad[$activeCharacter].yIndex;
		}
		if (!isObject($mazeRoom[%mouseIndexX, %mouseIndexY]))
		{
			if (!tileClearOfMonsters(%mouseIndexX, %mouseIndexY))
			{
				%cursorType = 2;
			}
			else if (tileHasObjectToGrab(%xIndex, %yIndex))		// Add trap cursor?
			{
				%cursorType = 3;
			}
			else
			{
				%cursorType = 0;
			}
		}
		else
		{
			// Check if the tile is a door tile.
			if ($mazeRoom[%mouseIndexX, %mouseIndexY].status == -4	||	// Opened door.
				$mazeRoom[%mouseIndexX, %mouseIndexY].status == -3)		// Closed door.
			{
				if (!tileClearOfMonsters(%mouseIndexX, %mouseIndexY))
				{
					%cursorType = 2;
				}
				else
				{
					%cursorType = 0;
				}
			}
			else
			{
				// Make sure it's not the elevator tile!
				if (%mouseIndexX == $stairsXIndex	&&
					%mouseIndexY == $stairsYIndex)
				{
					%cursorType = 0;
				}
				else
				{
					%cursorType = 1;
				}
			}
		}
		
		// Short-circuit cursor type if cursor is on squad member or monster!
		if (%mouseSquadMemberIndex != -1)
		{
			%cursorType = 3;
			createSquadMemberCursor();
		}
		else if (%mouseMonsterIndex != -1)
		{
			%cursorType = 2;
			createMonsterCursor();
		}
		else
		{
			createDefaultCursor();
		}
		
		if ($Game::AlwaysShowMoveIndicator)
		{
			$mouseMoveIndicator = createMouseIndicatorAnimation(%cursorType);
			// Shift position for new mouse cursor!
			%yPos -= 0.2;	// Ehhh... just a guess for now.
			// Reposition indicator.
			$mouseMoveIndicator.setPosition(%xPos, %yPos);
			$mouseMoveIndicator.xIndex = %mouseXIndex;
			$mouseMoveIndicator.yIndex = %mouseYIndex;
		}
	}
}

function inWeaponRange (%monsterIndex)
{
	%x = $playerSquad[$activeCharacter].xIndex;
	%y = $playerSquad[$activeCharacter].yIndex;
	for (%i = 0; %i < ($playerSquad[$activeCharacter].weapon).range; %i++)
	{
		switch ($playerSquad[$activeCharacter].facing)
		{
			case $northDirection:	%y--;
			case $southDirection:	%y++;
			case $eastDirection:	%x++;
			case $westDirection:	%x--;
		}
		if (!canFireThrough(%x, %y))
		{
			return false;
		}
		else if (monsterAtPosition(%x, %y) != -1)
		{
			return true;
		}
	}
	return false;
}