//------------------------------------------------------------------------------
// File: client_cmdsystem.cs
// This file is used for initializing the command system on the client
// Author: Matthew Rudge
//------------------------------------------------------------------------------

$CS_TARGETGROUP   = 0;
$CS_MAXCMDBTNS    = 41; // Max number of command buttons
$CS_MAXCMDBTNTEXT = 33; // Max number of command button text
$CS_MAXBLDGSTATUS = 5;  // Max number of building statuses
$CS_STARTDRAG     = 0;
$CS_ENDDRAG       = 0;
$CS_MAXDEPUTIES   = 3;
$CSC_LEFTBTN      = 0;
$CSC_RGHTBTN      = 0;
$CSC_ISSUED       = 0;

// Used for client->server->client delays in command processing
$CSC_PENDING      = 0;

////////////////////////////////////////////////////////////////////////////////
//! Initializes the client command system
////////////////////////////////////////////////////////////////////////////////
function slgBuildClientCommandSystem()
{   
   slgBuildCommandSystem(false);
   
   // Set up command buttons
   csInitCommandButtons();
   
   // Initialize globals
   $CSC_ISSUED = $CSC_NONE;
}

////////////////////////////////////////////////////////////////////////////////
//! Destroys the command system and stops it running
////////////////////////////////////////////////////////////////////////////////
function slgDestroyClientCommandSystem()
{
   slgShutdownCommandSystem();
}

////////////////////////////////////////////////////////////////////////////////
//! Starts the command system running
////////////////////////////////////////////////////////////////////////////////
function slgStartClientCommandSystem()
{
   slgStartCommandSystem();
}

////////////////////////////////////////////////////////////////////////////////
//! Initializes the command buttons to have a button index
////////////////////////////////////////////////////////////////////////////////
function csInitCommandButtons()
{  
   // Set index for buttons
   for(%i = 0; %i < $CS_MAXCMDBTNS; %i++) {
      %charBtnName = csGetCharacterButton(%i);
      %bldgBtnName = csGetBuildingButton(%i);
      %charBtnName.btnIndex = %i;
      %bldgBtnName.btnIndex = %i;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the name of the character command button at the specified index
//! \param %index Index of character command button
////////////////////////////////////////////////////////////////////////////////
function csGetCharacterButton(%index)
{
   return "CharCmdButton" @ %index;
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the name of the building command button at the specified index
//! \param %index Index of building command button
////////////////////////////////////////////////////////////////////////////////
function csGetBuildingButton(%index)
{
   return "BldgCmdButton" @ %index;
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the name of the character command button text at the specified index
//! \param %index Index of character command button
////////////////////////////////////////////////////////////////////////////////
function csGetCharacterBtnText(%index)
{
   return "CharCmdBtnText" @ %index;
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the name of the building command button text at the specified index
//! \param %index Index of building command button
////////////////////////////////////////////////////////////////////////////////
function csGetBuildingBtnText(%index)
{
   return "BldgCmdBtnText" @ %index;
}

////////////////////////////////////////////////////////////////////////////////
//! Called when the right mouse button is pressed to issue a command
//! \retval bool True if the command system handled the right click, false
//! otherwise
////////////////////////////////////////////////////////////////////////////////
function csCmdOnRightClick()
{
   // If we are in the select or target state we are going to handle the click
   if(CmdStateTracker.isInState($CSS_SELECT) ||
      CmdStateTracker.isInState($CSS_TARGET)) {
      $CSC_RGHTBTN = !$CSC_PENDING;
      return true;
   }
   
   // Command system did not handle click
   return false;
}

////////////////////////////////////////////////////////////////////////////////
//! Called when the left mouse button is pressed to issue a command
//! \param %bDown Will be non zero when mouse button is DOWN
//! \retval bool True if the command system handled the left click, false
//! otherwise
////////////////////////////////////////////////////////////////////////////////
function csCmdOnLeftClick(%bDown)
{
   // In target or execute mode command system handles left clicks
   if(CmdStateTracker.isInState($CSS_TARGET))
   {
      if (%bDown == 0)
      {
         $CSC_LEFTBTN = !$CSC_PENDING;
      }
      return true;
   }
   if(CmdStateTracker.isInState($CSS_EXECUTE))
   {
      return true;
   }
   
   // Command system did not handle click
   return false;
}

////////////////////////////////////////////////////////////////////////////////
//! Called when a button issues a command to the command system
//! \param %iCmd Command value issued
//! \retval bool True if the command system handled the button click, false
//! otherwise
////////////////////////////////////////////////////////////////////////////////
function csCmdOnButton(%iCmd)
{
   // Click handled in select or target state
   if(CmdStateTracker.isInState($CSS_SELECT) ||
      CmdStateTracker.isInState($CSS_TARGET)) {
      if(CmdInterpreter.isValidCommand(%iCmd) && !$CSC_PENDING) {
         $CSC_ISSUED = %iCmd;
      }
      return true;
   }
   
   // Command system did not handle button click
   return false;
}

////////////////////////////////////////////////////////////////////////////////
//! Clears target variables if in target state
////////////////////////////////////////////////////////////////////////////////
function csClearTargetState()
{
   // Clear target and command if in target state
   if(isObject(CmdStateTracker)) {
      if(CmdStateTracker.isInState($CSS_TARGET)) {
         // Clear the building from the cursor
         if(CmdStateTracker.getCommand() == $CSC_BUILD) {
            CancelBuilding();
         }
      
         // Clear the tool from the cursor
         else if(CmdStateTracker.getCommand() == $CSC_TOOL) {
            csCancelTool();
         }
      
         // Clear the command
         CmdStateTracker.clearCommand();
         CmdStateTracker.clearTarget();
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Updates objects selected within the command system and populates the HUD
//! with relevant commands
////////////////////////////////////////////////////////////////////////////////
function csUpdateSelection()
{
   CmdStateTracker.updateSelection();
   
   // Populate HUD
   slgPopulateCmdBtns();
}

////////////////////////////////////////////////////////////////////////////////
//! Starts the drag state for the command system, which will draw the drag line
//! and update the target and command
////////////////////////////////////////////////////////////////////////////////
function csCmdDragBegin()
{
   // All selected objects should be characters in order to drag
   %objs = gSelection.getSelectedGroup($SELECT_ID);
   if(!%objs.isOfObjectType($CID_CHARACTER)) {
      return;
   }
   
   $CS_STARTDRAG = true;
}

////////////////////////////////////////////////////////////////////////////////
//! Ends the drag state for the command system
////////////////////////////////////////////////////////////////////////////////
function csCmdDragEnd()
{
   $CS_ENDDRAG = true;
   
   if (isObject($DestinationObject) == true)
   {
      $DestinationObject.delete();
      $DestinationObject = 0;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Tests if the command system is currently dragging an object
//! \retval bool True if dragging an object
////////////////////////////////////////////////////////////////////////////////
function csCmdDragRunning()
{
   return CmdStateTracker.isInState($CSS_DRAG);
}

////////////////////////////////////////////////////////////////////////////////
//! Cancels the building process
////////////////////////////////////////////////////////////////////////////////
function CancelBuilding()
{
   if(PlayGui.hasObject())
   {
      // this removes the object from the cursor (no reason for this to fail)
      removeBuilding();
      
      BuildingRotate1.visible = false;
      BuildingRotate2.visible = false;
      BuildingRotate3.visible = false;

      // send a message to the server, which will handle deleting the object
      // only if it were an object to be placed (no destroying random objects
      // with hacking and only adds to resources if it is the specially placed
      // object)
      %client = ClientGroup.getObject(0);
      serverCmdCancelBuilding(%client);
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Cancels the tool use process
////////////////////////////////////////////////////////////////////////////////
function csCancelTool()
{
   toolsOnCancel(invClientGetSelectedItem());
}

////////////////////////////////////////////////////////////////////////////////
//! Used by command buttons that need server feedback on whether or not
//! the object creation succeeded. If successful, then the command system can
//! enter a target state with a command (needed due to multiple presses of 
//! button on client and client/server lag)
////////////////////////////////////////////////////////////////////////////////
function csBeginWaitForCmd()
{
   $CSC_PENDING = true;
   updateAttachedObject(false);
}

////////////////////////////////////////////////////////////////////////////////
//! Used by command buttons that need server feedback on whether or not
//! the object creation succeeded. If successful, then the command system can
//! enter a target state with a command (needed due to multiple presses of 
//! button on client and client/server lag)
////////////////////////////////////////////////////////////////////////////////
function csEndWaitForCmd()
{
   $CSC_PENDING = false;
   updateAttachedObject(true);
}

////////////////////////////////////////////////////////////////////////////////
//! Called by the server when an object creation for which the command target
//! state is reliant upon fails for some reason. This will allow the command
//! system to exit the pending state.
//! \param %cmd Reliant command
////////////////////////////////////////////////////////////////////////////////
function clientCmdCmdStatusFail(%cmd)
{
   csEndWaitForCmd();
}

// End client_cmdsystem.cs
