//------------------------------------------------------------------------------
// File: client_cmdcomponent.cs
// This file contains script functions for the command component and its 
// associated datatypes
// Author: Matthew Rudge
//------------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
//! Populates the given button with the command data
//! \param %btn Button to populate
//! \param %obj Object that has command button
////////////////////////////////////////////////////////////////////////////////
function CommandData::populateBtn(%this, %btn, %obj)
{
   if(!isObject(%btn)) {
      return;
   }
   
   // Check for invisibility flag
   if(%this.btnDisabledInvisible) {
      %btn.Visible = !csIsCommandDisabled(%this.getName());
   }
   else {
      %btn.Visible = true;
   }
   %btn.bmpTimer = 0;
   %btn.input    = true;
   
   // Images
   %btn.iconEnabled   = %this.btnIconEnabled;
   %btn.iconDisabled  = %this.btnIconDisabled;
   %btn.iconOffset    = %this.btnIconOffset;
   %btn.stateDisabled = %this.btnDisableImage;
   
   // Set cost text for command button if necessary
   %text = csGetCmdBtnText(%obj, %btn.btnIndex);
   if(isObject(%text)) {
      if(%this.goldCost > 0) {
         %text.stateUp = %this.goldCost;
         %text.Visible = !%btn.selected;
      }
      else {
         %text.stateUp = "";
      }
   }
   
   // Save button with this component
   %this.setCurrentButton(%btn);
}

////////////////////////////////////////////////////////////////////////////////
//! Updates the given button with the command data
//! \param %cmp Command component
////////////////////////////////////////////////////////////////////////////////
function CommandData::updateBtn(%this, %cmp, %btn, %index)
{
   if(!isObject(%btn)) {
      return;
   }
   
   // Update button
   %this.setCommand(%btn, %cmp);
   eval(%this.btnUpdate);
   
   // Default to enabled
   %btn.disabled = false;
   
   // Button always enabled if it is locked
   if(%this.xpCheck !$= "") {
      return;
   }
   
   // Button enabled if it is selected
   if(%btn.selected) {
      return;
   }
   
   // Check to see if command is externally disabled
   if(csIsCommandDisabled(%this.getName())) {
      %btn.disabled = true;
      return;
   }
   
   // always visible if it command is not disabled
   %btn.Visible = true;
   
   %object = %cmp.getObjectId();
   %ai = slgQueryInterface(%object, $CID_AI);
   if (isObject(%ai) == true)
   {
      if (($PLACE_DYNAMITE == true || %ai.toolActionsDisabled() == true)
         && %cmp.isToolDisabled(%index) == true)
      {
         %btn.disabled = true;
         return;
      }
   }
   
   // Check if object is disabled in any way
   if(%object.isDisabled()) {
      %btn.disabled = true;
      return;
   }

   // Execute command requirements
   for(%i = 0; %i < %this.getReqCount(); %i++) {
      if(!eval(%this.getReq(%i))) {
         %btn.disabled = true;
         return;
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Sets the button as selected if it should be selected
//! \param %btn Button to select or unselect, as needed
//! \param %obj Object that determines if button should be selected
////////////////////////////////////////////////////////////////////////////////
function CommandData::setSelection(%this, %btn, %obj)
{
   // Get button text
   %btnText = csGetCmdBtnText(%obj, %btn.btnIndex);
   
   // No selector for this command data
   if(%this.btnSelector $= "") {
      if(%btn.selected) {
         %btn.selected    = false;
         %btnText.Visible = true;
      }
      return;
   }
   
   // If the button should be selected then
   if(csIsButtonSelected(%this.btnSelector, %obj, %btn)) {
      // If it isn't selected then select it
      if(!%btn.selected) {
         %btn.selected    = true;
         %btnText.Visible = false;
      }
   }
   
   // If button shouldn't be selected then
   else {
      // If button is selected then unselect it
      if(%btn.selected) {
         %btn.selected    = false;
         %btnText.Visible = true;
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Sets the command for the button based on lock status and previous set
//! \param %btn Button to set
//! \param %cmdCmp Command component that owns CommandData data block
////////////////////////////////////////////////////////////////////////////////
function CommandData::setCommand(%this, %btn, %cmdCmp)
{
   // Experience check (button unlocked)
   if(%this.xpCheck $= "") {
      if(%cmdCmp.cmdSet[%btn.btnIndex] == false) {
         %btn.xpCheck = "";
         
         // Set command
         %btn.Command = %this.btnSelect;
      
         // This is a workaround for the command system and button structure...
         // Buttons are populated by the CommandData data block, and since one 
         // gunslinger datablock can populate one or more buttons, we need the specific
         // button that issued the command. %btn.Command does not allow for this (it
         // only evaluates the string as a code block), so I'm concatenating the
         // button index to the code block string.
         if(strstr(%btn.Command, "csExecuteRecruitSlingerCmdBtn") != -1) {
            %btn.Command = stripChars(%btn.Command, ");");
            %btn.Command = %btn.Command @ "," @ %btn.btnIndex @ ");";
            //echo(%btn.Command);
         }
         
         // We have set the command
         %cmdCmp.cmdSet[%btn.btnIndex] = true;
      }
   }
   
   // Button locked
   else {
      if(%cmdCmp.xpSet[%btn.btnIndex] == false) {
         %btn.xpCheck = %this.xpCheck;
          
         // We have set the experience
         %cmdCmp.xpSet[%btn.btnIndex] = true;
      }
   }
  
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the current button attached to the CommandData data block
////////////////////////////////////////////////////////////////////////////////
function CommandData::getCurrentButton(%this)
{
   return %this.btnName;
}

////////////////////////////////////////////////////////////////////////////////
//! Sets the current button attached to the CommandData data block
//! \param %btn Button to attach
////////////////////////////////////////////////////////////////////////////////
function CommandData::setCurrentButton(%this, %btn)
{
   %this.btnName = %btn;
}

////////////////////////////////////////////////////////////////////////////////
//! This method is called by the command component's update method.  It is
//! primarily used to update the command buttons of a selected unit.
//! \param %fTime Time since last update
////////////////////////////////////////////////////////////////////////////////
function CCmpCommand::onUpdate(%this, %fTime)
{   
   // Update command buttons if we are selected
   for(%i = 0; %i < %this.getCommandCount(); %i++) {
      %cmdData = %this.getCommand(%i);
      %btnName = %this.getCommandButton(%i);
      %cmdData.setCurrentButton(%btnName);
      %cmdData.updateBtn(%this, %btnName, %i);
      %cmdData.setSelection(%btnName, %this.getObjectId());
      
      // Re-populate button if command data has changed
      if(%this.getCommand(%i) != %cmdData) {
         %cmdData = %this.getCommand(%i);
         %this.onSelect(%btnName);
         %cmdData.populateBtn(%btnName, %this.getObjectId());
         %cmdData.setCurrentButton(%btnName);
         %cmdData.setCommand(%btnName, %this);
         %cmdData.setSelection(%btnName, %this.getObjectId());
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Called when the component is added to the simulation, this method is 
//! responsible for script initializations
////////////////////////////////////////////////////////////////////////////////
function CCmpCommand::onAdd(%this)
{
   %this.chooseCommands();
}

////////////////////////////////////////////////////////////////////////////////
//! Called when an object with a command component has been selected
//! \param %btn Current button being looked at
////////////////////////////////////////////////////////////////////////////////
function CCmpCommand::onSelect(%this, %btn)
{
   %this.cmdSet[%btn.btnIndex] = false;
   %this.xpSet[%btn.btnIndex]  = false;
}

////////////////////////////////////////////////////////////////////////////////
//! This method chooses commands for a command slot if it has a command list
//! \param %btnName Optional name of button for command we wish to choose
////////////////////////////////////////////////////////////////////////////////
function CCmpCommand::chooseCommands(%this, %btnName)
{
   // Choose for single button
   if(%btnName !$= "")
   {
      for(%i = 0; %i < %this.getCommandCount(); %i++) {
         // If we found the correct button then
         if(%this.getCommandButton(%i) $= %btnName) {
            // If it is a command list then choose command
            if(%this.isCommandList(%i)) {
               %random = getRandom(0, %this.getCommandListCount(%btnNum) - 1);
               %this.useListCmd[%i] = %random;
               
               // update the use list on the server
               %ghostID = ServerConnection.getGhostId(%this);
               commandToServer('UpdateUseList', %ghostID, %i, %random);
            }
         }
         
      }
   }
   
   // Choose for all buttons
   else {
      // Determine which command in command list to use if command slot is 
      // command list
      %data = "";
      for(%i = 0; %i < %this.getCommandCount(); %i++) {
         if(%this.isCommandList(%i)) {
            %random = %this.getRandomCommand(%i);
            %this.useListCmd[%i] = %random;
            %data = %data @ %random @ " ";
         }
      }
      
      if (%data !$= "")
      {
         // load the use list on the server
         %ghostID = ServerConnection.getGhostId(%this);
         commandToServer('SaveUseList', %ghostID, %data);
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the command stored at the specified slot index
//! \param %index Slot index
////////////////////////////////////////////////////////////////////////////////
function CCmpCommand::getCommand(%this, %index)
{
   // Get command from list
   if(%this.isCommandList(%index)) {
      return %this.getCommandDataInList(%index, %this.useListCmd[%index]);
   }
   
   // Get command
   else {
      return %this.getCommandData(%index);
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the command button for the command data stored at the specified 
//! slot index
//! \param %index Slot index
//! \retval string Name of command button
////////////////////////////////////////////////////////////////////////////////
function CCmpCommand::getCommandButton(%this, %index)
{
   return (csGetCmdBtn(%this.getObjectId(), %this.getCommandBtnIndex(%index)));
}

// this function is called from the server when the component is loaded
// in from a saved file
function clientCmdLoadUseList(%ghostID, %useList)
{
   %object = ServerConnection.resolveGhostId(%ghostID);

   %count = getWordCount(%useList);
   for (%index = 0; %index < %count; %index++)
   {
      %value = getWord(%useList, %index);
      %object.useListCmd[%index] = %value;
   }
}

// End client_cmdcomponent.cs
