//------------------------------------------------------------------------------
// File: svr_taskvertex.cs
// This file contains the TaskVertexState console methods.  The TaskVertexState
// represents the current state of a task vertex
// Author: Matthew Rudge
//------------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
//! Default onEnter callback method (checks zone to see if conditions
//! are already met and marks vertex and function info where needed)
////////////////////////////////////////////////////////////////////////////////
function TaskVertexState::onEnter(%this)
{
   // check if a zone function is in this vertex
   if (%this.hasFunctionType($TSF_ZONE) == false)
   {
      return;
   }
   
   // get the number of zone functions and for each zone
   // function, check if the specified requirements are
   // already in the zone (to mark the function complete)
   %count = %this.getFunctionTypeCount($TSF_ZONE);
   tsFillTagArrayValues($TSF_ZONE);
   for (%index = 0; %index < %count; %index++)
   {
      // check if the function is already complete
      if (%this.isFunctionComplete($TSF_ZONE, %index) == true)
      {
         continue;
      }
      
      // if there are no zones, we are done
      %zoneCount = %this.getInfoTagCount($TSF_ZONE, %index, $TSI_ZONENAME);
      if (%zoneCount == 0)
      {
         continue;
      }
      
      // get all of the zones
      %zones = 0;      
      for (%zoneIndex = 0; %zoneIndex < %zoneCount; %zoneIndex++)
      {
         %zones[%zoneIndex] = %this.getInfoValue($TSF_ZONE, %index, $TSI_ZONENAME, %zoneIndex);
      }
      
      // check if the tags are complete
      %complete = true;
      for (%tagIndex = 0; %tagIndex < $TSI_TAGARRAYCNT; %tagIndex++)
      {
         // check if this tag can be checked for the zone
         %tag = tsGetTagArrayValue(%tagIndex);
         if (%tag $= "" || %tag == $TSI_ZONENAME)
         {
            continue;
         }
         
         // get the number of values with this tag
         %valueCount = %this.getInfoTagCount($TSF_ZONE, %index, %tag);
         for (%valueIndex = 0; %valueIndex < %valueCount; %valueIndex++)
         {
            // get the value for the tag
            %value = %this.getInfoValue($TSF_ZONE, %index, %tag, %valueIndex);
         
            // check the value for each zone
            for (%zoneIndex = 0; %zoneIndex < %zoneCount; %zoneIndex++)
            {
               // get the zone
               %zone = %zones[%zoneIndex];
               
               // $TSI_SLGOBJTYPE
               if (%tagIndex == 0)
               {
                  %object = isTypeInZone(%value, %zone);
                  if (isObject(%object) == false)
                  {
                     %complete = false;
                  }
               }
               // $TSI_SLGOBJNAME
               else if (%tagIndex == 1)
               {
                  %object = isNameInZone(%value, %zone);
                  if (isObject(%object) == false)
                  {
                     %complete = false;
                  }
               }
               // $TSI_TEAM
               else if (%tagIndex == 3)
               {
                  %object = isTeamInZone(%value, %zone);
                  if (isObject(%object) == false)
                  {
                     %complete = false;
                  }
               }
               
               if (%complete == false)
               {
                  break;
               }
            }
         }
      }
      
      // check if the function is complete
      if (%complete == true)
      {
         %this.completeFunctionType($TSF_ZONE, %index);
      }
   }
   
   if (%this.areFunctionsComplete() == true)
   {
      %this.incCompleteCount();
   }
   
   // Check to see if the task vertex state can be completed
   if(%this.canBeCompleted())
   {
      if(TaskRuler.canMarkComplete(%this))
      {
         TaskModifier.markVertex(%this.getTaskId(), %this.getVertexId(), $TSV_CMPLETE);
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Default onExit callback method
////////////////////////////////////////////////////////////////////////////////
function TaskVertexState::onExit(%this)
{
}

////////////////////////////////////////////////////////////////////////////////
//! Default onUpdate callback method
//! \param %fTime Time since last update
////////////////////////////////////////////////////////////////////////////////
function TaskVertexState::onUpdate(%this, %fTime)
{
}

////////////////////////////////////////////////////////////////////////////////
//! Default onMessage callback method.  This method checks if the message
//! received completes a function within the TaskVertexState's function list.
//! If so, it will mark it as complete.  If all functions are completed, then
//! the TaskVertexState vertex will be marked as complete
//! \param %iMsgType Type of message received
//! \param %param String containing message information
////////////////////////////////////////////////////////////////////////////////
function TaskVertexState::onMessage(%this, %iMsgType, %param)
{
   // Get function type for message
   %iFctnType = tsMessageToFunction(%iMsgType);
   
   // Get function type count in vertex
   %iFctnCnt  = %this.getFunctionTypeCount(%iFctnType);
   
   // For each function of type in vertex do
   for(%i = 0; %i < %iFctnCnt; %i++) {
      // If this function is already complete then continue
      if(%this.isFunctionComplete(%iFctnType, %i)) {
         continue;
      }
      
      // If this function is completed by this message then complete it
      if(%this.functionMatches(%iFctnType,  %i, %param)) {
         %this.completeFunctionType(%iFctnType,  %i);
      }
   }

   // Check for function completion and increment completion count if all
   // function types have been completed
   if(%this.areFunctionsComplete())
      %this.incCompleteCount();
      
   // Check to see if the task vertex state can be completed
   if(%this.canBeCompleted()) {
      if(TaskRuler.canMarkComplete(%this)) {
         TaskModifier.markVertex(
         %this.getTaskId(), 
         %this.getVertexId(), 
         $TSV_CMPLETE
         );
      }
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Checks to see if this vertex object has an info pair tag in a specified
//! function
//! \param %fctn Function type
//! \param %iFctn Function index
//! \param %infoTag Info pair tag
//! \retval bool True if this vertex object has the info pair tag, false 
//! otherwise
////////////////////////////////////////////////////////////////////////////////
function TaskVertexState::hasInfoTag(%this, %fctn, %iFctn, %infoTag)
{
   // Vertex has info tag in function if occurrence is greater than zero
   %iTagCnt = %this.getInfoTagCount(%fctn, %iFctn, %infoTag);
   return (%iTagCnt > 0);
}

////////////////////////////////////////////////////////////////////////////////
//! Checks to see if an info pair matches or can be completed by the message
//! received
//! \param %fctn Function type to which info pair belongs
//! \param %iFctn i-th function of type to which info pair belongs
//! \param %infoTag Info pair tag type
//! \param %param String containing message information
////////////////////////////////////////////////////////////////////////////////
function TaskVertexState::infoPairMatches(%this, %fctn, %iFctn, %infoTag, %param)
{
   // Get info pair count for this function
   %iInfoCnt = %this.getInfoTagCount(%fctn, %iFctn, %infoTag);
   
   // For each info pair occurrence do
   for(%i = 0; %i < %iInfoCnt; %i++) {
      // Get the info value
      %value = %this.getInfoValue(%fctn, %iFctn, %infoTag, %i);
      
      // handle timer firing functionality
      if(%fctn == $TSF_TIMERFIRE){
         %vertexName = %this.getVertexName();
         %paramName = getWord(%param, 0);
         if (%paramName !$= %vertexName) {
            return false;
         }
      }
      // Evaluate the value
      else if(!tsEvalFunction(%fctn, %infoTag, %value, %param)) {
         return false;
      }
   }
      
   // All info pairs of type are complete
   return true;
}

////////////////////////////////////////////////////////////////////////////////
//! Checks to see if the function type matches or can be completed by the 
//! message received
//! \param %fctn Function type
//! \param %iFctn i-th function of type
//! \param %param String containing message information
////////////////////////////////////////////////////////////////////////////////
function TaskVertexState::functionMatches(%this, %fctn, %iFctn, %param)
{
   // Get all info pair tags for this function type
   tsFillTagArrayValues(%fctn);
   
   // For each info pair tag do
   for(%i = 0; %i < $TSI_TAGARRAYCNT; %i++) {
      %infoTag = tsGetTagArrayValue(%i);
      
      // Empty info pair tag check
      if(%infoTag $= "") {
         continue;
      }
      
      // If info pair tag is not complete then return false
      if(!%this.infoPairMatches(%fctn, %iFctn, %infoTag, %param)) {
         return false;
      }
   }
      
   // All info pairs of function are complete
   return true;
}

////////////////////////////////////////////////////////////////////////////////
//! Tests if the vertex has been completed by a message. This function is more
//! accurate if you are looking for message completion since it checks not only
//! if the vertex is in or moving to the complete state, but also if the current
//! completion count is greater or equal to the necessary completion count for 
//! the vertex
//! \retval bool True if the vertex has been truly completed by a message
////////////////////////////////////////////////////////////////////////////////
function TaskVertexState::hasBeenCompleted(%this)
{
   if(!%this.isMarkedComplete()) {
      return false;
   }
   return (%this.getCurrentCompleteCount() >= %this.getCompleteCount());
}
// End svr_taskvertex.cs
