//------------------------------------------------------------------------------
// File: client_taskDialogGui.cs
// This file contains the methods that will handle the task dialog hud elements
// Author: Matthew Rudge
//------------------------------------------------------------------------------

//-Global Values for task buttons, dialog, and icons----------------------------
$ProcessNextMsg = false;
$TaskDlgData    = 0;
$TaskDlgObj     = 0;
$TaskIcon      = "assets/client/ui/icons/taskbubble.png";
$TaskIconFocus = "assets/client/ui/icons/taskbubblehighlight.png";
$TaskIconExt   = "60 60";
$TaskIconWorld = "-.5 0 5";
$TaskBtn       = "assets/client/ui/icons/taskicon.png";
$TaskBtnFocus  = "assets/client/ui/icons/taskiconhighlight.png";
$TaskBtnExt    = "155 40";
$TaskBtnXOff   = 0;
$TaskBtnYOff   = -40;
$TaskEnabledImage = 0;
//------------------------------------------------------------------------------

//-Task Dialog Methods----------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
//! Populates the task dialog gui with task information
//! \param %dlgData Task dialog data
//! \param %dlgObj Object, if any, that appears in task dialog gui portrait 
//! window
//! \param %bProcessMsg Indicates whether or not to process the next message
//! in the TaskListener object after this dialog closes
////////////////////////////////////////////////////////////////////////////////
function populateTaskDlg(%dlgData, %dlgObj, %bProcessMsg)
{
   // For processing next message on close
   $ProcessNextMsg = %bProcessMsg;
   
   // Set dialog in gui control
   TaskDlgTaskName.stateUp  = %dlgData.getTaskName();
   TaskDlgTaskText0.stateUp = %dlgData.getTaskDialog(0);
   //TaskDlgImage.stateUp     = %dlgData.getTaskImage();
   
   // Set up buttons
   setTaskDlgBtnText(TaskDlgOkBtn, %dlgData.getOkayButtonText(), "Okay");
   setTaskDlgBtnText(TaskDlgAcceptBtn, %dlgData.getAcceptButtonText(), "Accept");
   setTaskDlgBtnText(TaskDlgCancelBtn, %dlgData.getCancelButtonText(), "Cancel");
   if (%dlgData.acceptDlg == $TaskButton::Accept) {
      TaskDlgOkBtn.Visible      = false;
      TaskDlgMoreBtn.Visible    = false;
      TaskDlgAcceptBtn.Visible  = true;
      TaskDlgCancelBtn.Visible  = true;
      TaskDlgAcceptBtn.disabled = acceptTaskDlgBtnDisabled(%dlgData);
   }
   else if (%dlgData.acceptDlg == $TaskButton::More) {
      TaskDlgOkBtn.Visible      = false;
      TaskDlgMoreBtn.Visible    = true;
      TaskDlgAcceptBtn.Visible  = false;
      TaskDlgCancelBtn.Visible  = false;
   }
   else {
      TaskDlgOkBtn.Visible      = true;
      TaskDlgMoreBtn.Visible    = false;
      TaskDlgAcceptBtn.Visible  = false;
      TaskDlgCancelBtn.Visible  = false;
   }
   
   DialPortFrame.visible = true;
   DialPortBG.visible = true;
   $TaskEnabledImage = 0;

   // Place object in dialog box if there is one
   TaskDlgCharacterName.stateUp = "";
   if(isObject(%dlgData.image)) {
      DialPortFrame.visible = false;
      DialPortBG.visible = false;
      TaskDialogHud.addGuiControl(%dlgData.image);
      %dlgData.image.visible = true;
      $TaskEnabledImage = %dlgData.image;
      commandToServer('SetTaskPortraitTarget', 0);
   }
   else if(isObject(%dlgObj)) {
      %firstNameEnd = strpos(%dlgObj.name, " ");
      TaskDlgCharacterName.stateUp = getSubStr(%dlgObj.name, 0, %firstNameEnd);
      commandToServer('SetTaskPortraitTarget', ServerConnection.getGhostID(%dlgObj));
   }
   else {
      commandToServer('SetTaskPortraitTarget', 0);
   }
   
   // Save for later use (removal when player selects okay or accept)
   saveTaskDlgData(%dlgData, %dlgObj);
   
   // Show dialog
   Canvas.pushDialog(TaskDialogGui);
   playSFXSound(AudioDialogPopup);
   slgStackPause();
   $GameMenuLoaded = true;
}

////////////////////////////////////////////////////////////////////////////////
//! Closes the task dialog window
////////////////////////////////////////////////////////////////////////////////
function closeTaskDlg()
{
   // Remove dialog from gui
   $GameMenuLoaded = false;
   slgStackUnpause();
   Canvas.popDialog(TaskDialogGui);
   
   // Process next message if necessary
   if($ProcessNextMsg) {
      TaskListener.processNextMessage();
      $ProcessNextMsg = false;
   }
   
   // if an image is present on the task dialog, close it
   if (isObject($TaskEnabledImage) == true)
   {
      $TaskEnabledImage.visible = false;
      $TaskEnabledImage = 0;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Pushes a task dialog object to an object for later retrieval
//! \param %dlgData Task dialog object
//! \param %dlgObj Game object receiving dialog data
////////////////////////////////////////////////////////////////////////////////
function pushTaskDlg(%dlgData, %dlgObj)
{
   // Push dialog to object
   %dlgObj.pushTaskDialog(%dlgData);
   
   // Pop task button for character if it doesn't have one
   if(%dlgObj.numTaskDialog() == 1) {
      createTaskIcon(%dlgObj);
      createTaskBtn(%dlgData, %dlgObj);
   }
   else {
      createTaskBtn(%dlgData, %dlgObj);
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Pops a task dialog object from an object
//! \param %dlgData Task dialog object
//! \param %dlgObj Game object that contains dialog
////////////////////////////////////////////////////////////////////////////////
function popTaskDlg(%dlgData, %dlgObj)
{
   if(!isObject(%dlgObj)) {
      return;
   }
   
   %dlgObj.popTaskDialogObject(%dlgData);
   
   // Get button and remove it from stack
   %btnCount = %dlgObj.btnCount;
   for(%i = 0; %i < %dlgObj.btnCount; %i++) {
      if(%dlgObj.taskBtn[%i].taskData == %dlgData) {
         %dlgObj.taskBtn[%i].delete();
         %dlgObj.taskBtn[%i] = "";
         %btnCount--;
         break;
      }
   }
   for(%i; %i < %dlgObj.btnCount; %i++) {
      %dlgObj.taskBtn[%i] = %dlgObj.taskBtn[%i + 1];
   }
   %dlgObj.btnCount = %btnCount;
   
   // Release task icon button
   if(%dlgObj.btnCount == 0) {
      if(isObject(%dlgObj.taskBtn)) {
         %dlgObj.taskBtn.delete();
      }
      %dlgObj.taskBtn = "";
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Called when the task dialog "okay" button was pressed or when the task
//! dialog "accept" button was successful
////////////////////////////////////////////////////////////////////////////////
function onTaskDlgAccept()
{   
   // Remove dialog from object
   popTaskDlg($TaskDlgData, $TaskDlgObj);
    
   %ghost = ServerConnection.getGhostID($TaskDlgObj);
   
   // Let server know that click dialog has been closed
   if($TaskDlgData.onClickDlg) {
      commandToServer('OnClickDlgDone', %ghost, $TaskDlgData.dlgDataId, $TaskDlgObj.numTaskDialog());
   }
   // Let server know that the pop-up dialog has been closed
   else {
      commandToServer('OnPopUpDlgDone', %ghost, $TaskDlgData.dlgDataId);
   }
   
   // Update task dialog buttons
   repositionTaskBtns($TaskDlgObj);
   
   // Delete task dialog object
   destroyTaskDlgData($TaskDlgData);
   
   // Reset saved dialog values
   clearTaskDlgData();
   
   // Close dialog
   closeTaskDlg();
}

////////////////////////////////////////////////////////////////////////////////
//! Sets the text on a task dialog button
//! \param %btn Button to receive text
//! \param %text Text for button
//! \param %default Default text for button if %text is an empty string
////////////////////////////////////////////////////////////////////////////////
function setTaskDlgBtnText(%btn, %text, %default)
{
   if(%text !$= "") {
      %btn.textUp = %text;
   }
   else {
      %btn.textUp = %default;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Tests whether the task dialog gui accept button should be disabled
//! \param %dlgData Task dialog object that contains resource cost information
////////////////////////////////////////////////////////////////////////////////
function acceptTaskDlgBtnDisabled(%dlgData)
{
   if(!isObject(%dlgData)) {
      return;
   }
   
   // For each resource cost do
   %count = %dlgData.getAcceptCostCount();
   for(%i = 0; %i < %count; %i++) {
      %rsrcCount = rsGetResourceCount(%dlgData.getAcceptCostResource(%i));
      if(%rsrcCount < %dlgData.getAcceptCostResourceCount(%i)) {
         return true;
      }
   }
   
   // Enabled
   return false;
}

////////////////////////////////////////////////////////////////////////////////
//! Task dialog gui "more" button select callback
////////////////////////////////////////////////////////////////////////////////
function TaskDlgMoreBtn::buttonSelect(%this)
{
   // Task dialog "more"
   onTaskDlgAccept();
}

////////////////////////////////////////////////////////////////////////////////
//! Task dialog gui "okay" button select callback
////////////////////////////////////////////////////////////////////////////////
function TaskDlgOkBtn::buttonSelect(%this)
{
   // Task dialog "okay"
   onTaskDlgAccept();
}

////////////////////////////////////////////////////////////////////////////////
//! Task dialog gui "cancel" button select callback
////////////////////////////////////////////////////////////////////////////////
function TaskDlgCancelBtn::buttonSelect(%this)
{
   // Reset saved dialog values
   clearTaskDlgData();
   
   // Close dialog
   closeTaskDlg();
}

////////////////////////////////////////////////////////////////////////////////
//! Task dialog gui "accept" button select callback. Currently this method
//! calls the server for resolving resource costs for acceptance, however, the
//! client dictates what the resource costs are in this method through the task
//! dialog object. In a true network environment, this should never happen.
////////////////////////////////////////////////////////////////////////////////
function TaskDlgAcceptBtn::buttonSelect()
{
   // Fill parameter for command
   %rscstr = "";
   %size = $TaskDlgData.getAcceptCostCount();
   for(%i = 0; %i < %size; %i++) {
      if(%rscstr $= "") {
         %rscstr = $TaskDlgData.getAcceptCostResource(%i);
      }
      else {
         %rscstr = %rscstr SPC $TaskDlgData.getAcceptCostResource(%i);
      }
      %rscstr = %rscstr SPC $TaskDlgData.getAcceptCostResourceCount(%i);
   }
   
   // Notify server that task has been accepted
   commandToServer('AcceptTaskBtnClk', %rscstr);
   
}

////////////////////////////////////////////////////////////////////////////////
//! Destroys the task dialog data object
//! \param %dlgData Task dialog data object
////////////////////////////////////////////////////////////////////////////////
function destroyTaskDlgData(%dlgData)
{
   if(!isObject(%dlgData)) {
      return;
   }
   
   // Delete image attached to dialog data object
   if(isObject(%dlgData.image)) {
      %dlgData.image.delete();
   }
   
   // Delete dialog data object
   %dlgData.delete();
}

////////////////////////////////////////////////////////////////////////////////
//! Removes all dialog on an object
//! \param %dlgObj Object with dialog
//! \param %bNoMsg True if no message is to display
////////////////////////////////////////////////////////////////////////////////
function destroyAllTaskDialog(%dlgObj, %bNoMsg)
{
   if(!isObject(%dlgObj)) {
      return;
   }
   
   // No dialog to destroy
   if(%dlgObj.numTaskDialog() <= 0) {
      return;
   }
   
   while(%dlgObj.numTaskDialog() > 0) {
      %dlgData = %dlgObj.getTaskDialog(0);
      popTaskDlg(%dlgData, %dlgObj);
      destroyTaskDlgData(%dlgData);
   }
   
   // Notify server that no dialogs exist with this object
   commandToServer('OnDlgDestroy', ServerConnection.getGhostID(%dlgObj), 0);
   
   if(!%bNoMsg) {
      %string = slgGetUIString("id_dialogquests_lost");
      %string = slgFormatUIString(%string, %dlgObj.name);
      alertPushMsg(%string);
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Server callback when the resource cost for acceptance has been examined
////////////////////////////////////////////////////////////////////////////////
function clientCmdAcceptTaskBtnClkAck(%bSuccess)
{
   // Successful resource deduction
   if(%bSuccess) {
      onTaskDlgAccept();
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Called from the server to destroy a task dialog data object on an object
//! \param %dlgId Id of task dialog data object
//! \param %dlgObj Object speaking dialog
////////////////////////////////////////////////////////////////////////////////
function clientCmdDestroyTaskDlg(%dlgId, %dlgObj)
{
   %dlgObj = ServerConnection.resolveGhost(%dlgObj);
   if(!isObject(%dlgObj)) {
      return;
   }
   
   // Find task dialog data object to remove
   %count = %dlgObj.numTaskDialog();
   for(%i = 0; %i < %count; %i++) {
      %dlgData = %dlgObj.getTaskDialog(%i);
      if(!isObject(%dlgData)) {
         continue;
      }
      if(%dlgData.dlgDataId $= %dlgId) {
         popTaskDlg(%dlgData, %dlgObj);
         repositionTaskBtns(%dlgObj);
         destroyTaskDlgData(%dlgData);
         break;
      }
   }
   
   // Notify server of number of task dialogs on character
   commandToServer('OnDlgDestroy', ServerConnection.getGhostID(%dlgObj), %dlgObj.numTaskDialog());
}

////////////////////////////////////////////////////////////////////////////////
//! Called from the server to destroy all task dialog data objects on an object
//! \param %dlgObj Object speaking dialog
////////////////////////////////////////////////////////////////////////////////
function clientCmdDestroyAllTaskDlg(%dlgObj, %noMsg)
{
   destroyAllTaskDialog(ServerConnection.resolveGhost(%dlgObj), %noMsg);
}
//------------------------------------------------------------------------------

//-Task Icon and Button Methods-------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
//! Creates a task icon above the desired object
//! \param %dlgObj Target object of task icon
////////////////////////////////////////////////////////////////////////////////
function createTaskIcon(%dlgObj)
{
   // Create button
   %taskBtn = new SLTaskButton("TaskIcon") {
      extent  = $TaskIconExt;
      visible = "1";
      bitmap  = $TaskIcon;
      
      // gui target control functionality
      target          = %dlgObj;
      renderFront     = false;
      worldOffset     = $TaskIconWorld;
      highlightBitmap = $TaskIconFocus;
   };
   TaskButtonGroup.addGuiControl(%taskBtn);
   //TaskButtonGroup.addGuiControlFirst(%taskBtn);
   
   // Add button to object
   %dlgObj.taskBtn = %taskBtn;
}

////////////////////////////////////////////////////////////////////////////////
//! Creates a task button above the desired object
//! \param %dlgData Task dialog object data when button is pressed
//! \param %dlgObj Target object of task button
////////////////////////////////////////////////////////////////////////////////
function createTaskBtn(%dlgData, %dlgObj)
{
   // Initialize button count
   if(%dlgObj.btnCount $= "") {
      %dlgObj.btnCount = 0;
   }
   
   // Create task button   
   %taskBtn = new SLTaskButton("TaskButton") {
      extent  = $TaskBtnExt;
      visible = "0";
      bitmap  = $TaskBtn;
      Profile = "TaskButtonProfile";
      
      // gui target control functionality
      target          = %dlgObj;
      taskData        = %dlgData;
      renderFront     = true;
      worldOffset     = $TaskIconWorld;
      
      // task button
      taskText        = %dlgData.getTaskName();
      highlightBitmap = $TaskBtnFocus;
      textOffset      = "30 0";
   };
   TaskButtonGroup.addGuiControl(%taskbtn);
   //TaskButtonGroup.addGuiControlFirst(%taskBtn);
   
   // Add button to object
   %dlgObj.taskBtn[%dlgObj.btnCount] = %taskBtn;
   %dlgObj.btnCount++;
   
   // Reposition buttons
   repositionTaskBtns(%dlgObj);
}

////////////////////////////////////////////////////////////////////////////////
//! Hides or shows the task buttons above a target object
//! \param %dlgObj Target object
//! \param %bShow True if the buttons are to show, false to hide
////////////////////////////////////////////////////////////////////////////////
function showTaskBtns(%dlgObj, %bShow)
{
   // Target object does not have buttons
   if(%dlgObj.btnCount $= "") {
      return;
   }
   
   // For each task button do
   for(%i = 0; %i < %dlgObj.btnCount; %i++) {
      // Make visible
      %dlgObj.taskBtn[%i].visible = %bShow;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Repositions the task buttons after one has been added or removed from the
//! task button list
//! \param %dlgObj Object with task buttons
////////////////////////////////////////////////////////////////////////////////
function repositionTaskBtns(%dlgObj)
{
   if(!isObject(%dlgObj)) {
      return;
   }
   
   // For each task button in the object do
   for(%i = 0; %i < %dlgObj.btnCount; %i++) {
      // Get task button
      %taskBtn = %dlgObj.taskBtn[%i];
      
      // Position earliest task buttons at top
      %xPos = $TaskBtnXOff + ((%dlgObj.btnCount - (%i + 1)) * $TaskBtnXOff);
      %yPos = $TaskBtnYOff + ((%dlgObj.btnCount - (%i + 1)) * $TaskBtnYOff);
      
      // Set position on button
      %taskBtn.screenOffset = %xPos SPC %yPos;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Query to determine if task buttons are currently visible
//! \param %dlgObj Object with task buttons
////////////////////////////////////////////////////////////////////////////////
function areTaskBtnsVisible(%dlgObj)
{
   // Target object does not have buttons
   if(%dlgObj.btnCount $= "") {
      return false;
   }
   return (%dlgObj.taskBtn[0].visible);
}

////////////////////////////////////////////////////////////////////////////////
//! Saves task dialog and task object data when the task dialog gui is shown
//! \param %dlgData Task dialog data
//! \param %dlgObj Task object
////////////////////////////////////////////////////////////////////////////////
function saveTaskDlgData(%dlgData, %dlgObj)
{
   $TaskDlgData = %dlgData;
   $TaskDlgObj  = %dlgObj;
}

////////////////////////////////////////////////////////////////////////////////
//! Clears the saved task dialog and task object data when the task dialog gui
//! is hidden
////////////////////////////////////////////////////////////////////////////////
function clearTaskDlgData()
{
   $TaskDlgData = 0;
   $TaskDlgObj  = 0;
}

////////////////////////////////////////////////////////////////////////////////
//! Called when a task button or task icon has been selected. This method is
//! responsible for showing/hiding task buttons and showing the task dialog gui.
////////////////////////////////////////////////////////////////////////////////
function SLTaskButton::buttonSelect(%this)
{
   // Opens more buttons or generates dialog
   if(%this.getName() $= "TaskIcon") {
      if(areTaskBtnsVisible(%this.target)) {
         showTaskBtns(%this.target, false);
      }
      else {
         // Open more buttons
         if(%this.target.numTaskDialog() > 1) {
            showTaskBtns(%this.target, true);
         }
         // Generate dialog
         else {
            populateTaskDlg(%this.target.taskBtn[0].taskData, %this.target, false);
         }
      }
   }
   
   // Opens dialog
   else {
      populateTaskDlg(%this.taskData, %this.target, false);
   }
   
   // Select object with dialog
   if(!isSelected(%this.target) && %this.target.showMesh) {
      selectObject(%this.target);
   }
}
//------------------------------------------------------------------------------

// End client_taskDialogGui.cs
