// =============================================================================
// KEYBINDS MENU
// =============================================================================
function ControlsMenuDefaultsButton::onClick(%this)
{
   //For this to work with module-style, we have to figure that somewhere, we'll set where our default keybind script is at.
   //This can be hardcoded in your actual project.
   //exec($KeybindPath);
   //ControlsMenu.reload();
}

function getMapDisplayName( %device, %action )
{
	if ( %device $= "keyboard" )
		return( %action );		
	else if ( strstr( %device, "mouse" ) != -1 )
	{
		// Substitute "mouse" for "button" in the action string:
		%pos = strstr( %action, "button" );
		if ( %pos != -1 )
		{
			%mods = getSubStr( %action, 0, %pos );
			%object = getSubStr( %action, %pos, 1000 );
			%instance = getSubStr( %object, strlen( "button" ), 1000 );
			return( %mods @ "mouse" @ ( %instance + 1 ) );
		}
		else
			error( "Mouse input object other than button passed to getDisplayMapName!" );
	}
	else if ( strstr( %device, "joystick" ) != -1 )
	{
		// Substitute "joystick" for "button" in the action string:
		%pos = strstr( %action, "button" );
		if ( %pos != -1 )
		{
			%mods = getSubStr( %action, 0, %pos );
			%object = getSubStr( %action, %pos, 1000 );
			%instance = getSubStr( %object, strlen( "button" ), 1000 );
			return( %mods @ "joystick" @ ( %instance + 1 ) );
		}
		else
	   { 
	      %pos = strstr( %action, "pov" );
         if ( %pos != -1 )
         {
            %wordCount = getWordCount( %action );
            %mods = %wordCount > 1 ? getWords( %action, 0, %wordCount - 2 ) @ " " : "";
            %object = getWord( %action, %wordCount - 1 );
            switch$ ( %object )
            {
               case "upov":   %object = "POV1 up";
               case "dpov":   %object = "POV1 down";
               case "lpov":   %object = "POV1 left";
               case "rpov":   %object = "POV1 right";
               case "upov2":  %object = "POV2 up";
               case "dpov2":  %object = "POV2 down";
               case "lpov2":  %object = "POV2 left";
               case "rpov2":  %object = "POV2 right";
               default:       %object = "";
            }
            return( %mods @ %object );
         }
         else
            error( "Unsupported Joystick input object passed to getDisplayMapName!" );
      }
	}
	else if ( strstr( %device, "gamepad" ) != -1 )
	{
	   return %action;
	   
	   %pos = strstr( %action, "button" );
		if ( %pos != -1 )
		{
			%mods = getSubStr( %action, 0, %pos );
			%object = getSubStr( %action, %pos, 1000 );
			%instance = getSubStr( %object, strlen( "button" ), 1000 );
			return( %mods @ "joystick" @ ( %instance + 1 ) );
		}
		else
	   { 
	      %pos = strstr( %action, "thumb" );
         if ( %pos != -1 )
         {
            //%instance = getSubStr( %action, strlen( "thumb" ), 1000 );
            //return( "thumb" @ ( %instance + 1 ) );
            return %action;
         }
         else
            error( "Unsupported gamepad input object passed to getDisplayMapName!" );
      }
	}
		
	return( "" );		
}

function buildFullMapString( %index, %actionMap, %deviceType )
{
   %name       = $RemapName[%index];
   %cmd        = $RemapCmd[%index];
   
   %temp = %actionMap.getBinding( %cmd );
   if ( %temp $= "" )
      return %name TAB "";

   %mapString = "";

   %count = getFieldCount( %temp );
   for ( %i = 0; %i < %count; %i += 2 )
   {
      if ( %mapString !$= "" )
         continue;
         //%mapString = %mapString @ ", ";
         
      %device = getField( %temp, %i + 0 );
      %object = getField( %temp, %i + 1 );
      
      if(%deviceType !$= "" && !startsWith(%device, %deviceType))
         continue;
         
      %mapString = %mapString @ getMapDisplayName( %device, %object );
   }

   return %name TAB %mapString; 
}

function fillRemapList()
{
   %device = $remapListDevice;
   
	OptionsMenuSettingsList.clearRows();

   //build out our list of action maps
   %actionMapCount = ActionMapGroup.getCount();
   
   %actionMapList = "";
   for(%i=0; %i < %actionMapCount; %i++)
   {
      %actionMap = ActionMapGroup.getObject(%i);
      
      if(%actionMap == GlobalActionMap.getId())
         continue;
      
      %actionMapName = %actionMap.humanReadableName $= "" ? %actionMap.getName() : %actionMap.humanReadableName;
      
      if(%actionMapList $= "")
         %actionMapList = %actionMapName;
      else
         %actionMapList = %actionMapList TAB %actionMapName;
   }
   
   //If we didn't find any valid actionMaps, then just exit out
   if(%actionMapList $= "")
      return;
      
   if($activeRemapControlSet $= "")
      $activeRemapControlSet = getField(%actionMapList, 0);
   
   OptionsMenuSettingsList.addOptionRow("Control Set", %actionMapList, false, "controlSetChanged", -1, -30, true, "Which keybind control set to edit", $activeRemapControlSet);
	
   for ( %i = 0; %i < $RemapCount; %i++ )
   {
      if(%device !$= "" && %device !$= $RemapDevice[%i])
         continue;
         
      %actionMapName = $RemapActionMap[%i].humanReadableName $= "" ? $RemapActionMap[%i].getName() : $RemapActionMap[%i].humanReadableName; 
         
      if($activeRemapControlSet !$= %actionMapName)
         continue;
         
      %keyMap = buildFullMapString( %i, $RemapActionMap[%i], %device );
      %description = $RemapDescription[%i];
      
      OptionsMenuSettingsList.addKeybindRow(getField(%keyMap, 0), getButtonBitmap(%device, getField(%keyMap, 1)), "doKeyRemap", -1, -15, true, %description);
   }

   OptionsMenuSettingsList.refresh();
      //OptionsMenu.addRow( %i, %this.buildFullMapString( %i ) );
}

function controlSetChanged()
{
   $activeRemapControlSet = OptionsMenuSettingsList.getCurrentOption(0);
   fillRemapList();
}

function doKeyRemap( %rowIndex )
{
   %rowIndex--; //Offset the rowIndex to account for controlset option
   %name = $RemapName[%rowIndex];

	RemapDlg-->OptRemapText.setValue( "Re-bind \"" @ %name @ "\" to..." );
	OptRemapInputCtrl.index = %rowIndex;
	Canvas.pushDialog( RemapDlg );
}

function ControlsMenuRebindButton::onClick(%this)
{
   %name = $RemapName[%this.keybindIndex];
   RemapDlg-->OptRemapText.setValue( "Re-bind \"" @ %name @ "\" to..." );
   
   OptRemapInputCtrl.index = %this.keybindIndex;
   OptRemapInputCtrl.optionIndex = %this.optionIndex;
   Canvas.pushDialog( RemapDlg );
}

function OptRemapInputCtrl::onInputEvent( %this, %device, %action )
{
   //error( "** onInputEvent called - device = " @ %device @ ", action = " @ %action @ " **" );
   Canvas.popDialog( RemapDlg );

   // Test for the reserved keystrokes:
   if ( %device $= "keyboard" )
   {
      // Cancel...
      if ( %action $= "escape" )
      {
         // Do nothing...
         return;
      }
   }

   %cmd  = $RemapCmd[%this.index];
   %name = $RemapName[%this.index];
   %actionMap = $RemapActionMap[%this.index];

   // Grab the friendly display name for this action
   // which we'll use when prompting the user below.
   %mapName = getMapDisplayName( %device, %action );
   
   // Get the current command this action is mapped to.
   %prevMap = %actionMap.getCommand( %device, %action );
   
   //TODO: clear all existant keybinds to a command and then bind it so we only have a single one at all times
   unbindExtraActions( %cmd, %actionMap, 0 );
   unbindExtraActions( %cmd, %actionMap, 1 );

   // If nothing was mapped to the previous command 
   // mapping then it's easy... just bind it.
   if ( %prevMap $= "" )
   {
      //unbindExtraActions( %cmd, %actionMap, 1 );
      %actionMap.bind( %device, %action, %cmd );
      
      fillRemapList();
      return;
   }

   // If the previous command is the same as the 
   // current then they hit the same input as what
   // was already assigned.
   if ( %prevMap $= %cmd )
   {
      //unbindExtraActions( %cmd, %actionMap, 0 );
      %actionMap.bind( %device, %action, %cmd );

      fillRemapList();
      return;   
   }

   // Look for the index of the previous mapping.
   %prevMapIndex = findRemapCmdIndex( %prevMap );
   
   // If we get a negative index then the previous 
   // mapping was to an item that isn't included in
   // the mapping list... so we cannot unmap it.
   if ( %prevMapIndex == -1 )
   {
      MessageBoxOK( "Remap Failed", "\"" @ %mapName @ "\" is already bound to a non-remappable command!" );
      return;
   }

   // Setup the forced remapping callback command.
   %callback = "redoMapping(" @ %device @ ", " @ %actionMap @ ", \"" @ %action @ "\", \"" @
                              %cmd @ "\", " @ %prevMapIndex @ ", " @ %this.index @ ");";
   
   // Warn that we're about to remove the old mapping and
   // replace it with another.
   %prevCmdName = $RemapName[%prevMapIndex];
   Canvas.pushDialog( RemapConfirmDlg );
   
   RemapConfirmationText.setText("\"" @ %mapName @ "\" is already bound to \""
      @ %prevCmdName @ "\"! Do you wish to replace this mapping?");
   RemapConfirmationYesButton.command = "redoMapping(" @ %device @ ", " @ %actionMap @ ", \"" @ %action @ "\", \"" @
                              %cmd @ "\", " @ %prevMapIndex @ ", " @ %this.index @ "); Canvas.popDialog();";
   RemapConfirmationNoButton.command = "Canvas.popDialog();";
   
   /*MessageBoxYesNo( "Warning",
      "\"" @ %mapName @ "\" is already bound to \""
      @ %prevCmdName @ "\"!\nDo you wish to replace this mapping?",
       %callback, "" );*/
}

function findRemapCmdIndex( %command )
{
	for ( %i = 0; %i < $RemapCount; %i++ )
	{
		if ( %command $= $RemapCmd[%i] )
			return( %i );			
	}
	return( -1 );	
}

/// This unbinds actions beyond %count associated to the
/// particular actionMap %commmand.
function unbindExtraActions( %command, %actionMap, %count )
{
   %temp = %actionMap.getBinding( %command );
   if ( %temp $= "" )
      return;

   %count = getFieldCount( %temp ) - ( %count * 2 );
   for ( %i = 0; %i < %count; %i += 2 )
   {
      %device = getField( %temp, %i + 0 );
      %action = getField( %temp, %i + 1 );
      
      %actionMap.unbind( %device, %action );
   }
}

function redoMapping( %device, %actionMap, %action, %cmd, %oldIndex, %newIndex )
{
	//%actionMap.bind( %device, %action, $RemapCmd[%newIndex] );
	%actionMap.bind( %device, %action, %cmd );
	
	fillRemapList();
}