<?php
/**
 * ###############################################
 *
 * SWIFT Framework
 * _______________________________________________
 *
 * @author		Varun Shoor
 *
 * @package		SWIFT
 * @copyright	Copyright (c) 2001-2012, Kayako
 * @license		http://www.kayako.com/license
 * @link		http://www.kayako.com
 *
 * ###############################################
 */

/**
 * The View Ticket Controller
 *
 * @author Varun Shoor
 */
class Controller_Ticket extends Controller_staff
{
	// Core Constants
	const MENU_ID = 2;
	const NAVIGATION_ID = 1;

	/**
	 * Constructor
	 *
	 * @author Varun Shoor
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function __construct()
	{
		parent::__construct();

		$this->Load->Library('CustomField:CustomFieldRendererStaff');
		$this->Load->Library('CustomField:CustomFieldManager');

		$this->Language->Load('staff_ticketsmain');
		$this->Language->Load('staff_ticketsmanage');

		SWIFT_Ticket::LoadLanguageTable();

		return true;
	}

	/**
	 * Destructor
	 *
	 * @author Varun Shoor
	 * @return bool "true" on Success, "false" otherwise
	 */
	public function __destruct()
	{
		parent::__destruct();

		return true;
	}

	/**
	 * View a ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @param int $_ticketLimitOffsetIncoming (OPTIONAL) The Incoming offset
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function View($_ticketID = '', $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1, $_ticketLimitOffset = 0, $_ticketLimitOffsetIncoming = -2) {
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (empty($_ticketID)) {
			$this->Load->Controller('Manage')->Index();

			return false;
		}

		$_ticketLimitOffsetIncoming = intval($_ticketLimitOffsetIncoming);
		if ($_ticketLimitOffsetIncoming != -2)
		{
			$_ticketLimitOffset = $_ticketLimitOffsetIncoming;
		}

		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
			$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
			$this->UserInterface->Footer();

			return false;
		}

		// Check permission
		/*
		 * Improvement - Bishwanath Jha
		 *
		 * SWIFT-1339 Restrict staff to be able to view assigned tickets ONLY
		 *
		 * Comments : Check if restriction for Group (Can View unassigned Tickets, Can View All Tickets) is set?
		 */
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanviewtickets') == '0' ||
			($_SWIFT_TicketObject->GetProperty('ownerstaffid') == 0 && $_SWIFT->Staff->GetPermission('staff_tcanviewunassign') == '0') ||
			($_SWIFT_TicketObject->GetProperty('ownerstaffid') != 0 && $_SWIFT_TicketObject->GetProperty('ownerstaffid') != $_SWIFT->Staff->GetStaffID() && $_SWIFT->Staff->GetPermission('staff_tcanviewall') == '0')
		) {
			$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
			$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
			$this->UserInterface->Footer();

			return false;

		}

		//Don't allow deleted ticket to be displayed
/*		if (!$_SWIFT_TicketObject->GetProperty('departmentid')) {
			$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
			$this->UserInterface->DisplayError($this->Language->Get('titleticketdeleted'), $this->Language->Get('msgticketdeleted'));
			$this->UserInterface->Footer();

			return false;
		}*/

		if (is_numeric($_ticketLimitOffset)) {
			$_ticketLimitOffset = intval($_ticketLimitOffset);
		} else {
			$_ticketLimitOffset = 0;
		}

		$_SWIFT_UserObject = $_SWIFT_TicketObject->GetUserObject();
		$_SWIFT_UserOrganizationObject = $_SWIFT_TicketObject->GetUserOrganizationObject();

		$_ticketLinkedTableContainer = SWIFT_TicketLinkedTable::RetrieveOnTicket($_SWIFT_TicketObject);

		SWIFT::Set('ticketurlsuffix', $_listType . '/' . $_departmentID . '/' . $_ticketStatusID . '/' . $_ticketTypeID . '/' . $_ticketLimitOffset);

		// Ticket Post Processing
		$_variableContainer = array();
		$_ticketPostCount = $_SWIFT_TicketObject->GetTicketPostCount();

		$_ticketPostOffset = intval($_ticketLimitOffset);
		$_ticketPostLimitCount = false;
		if ($this->Settings->Get('t_enpagin') == '1') {
			$_ticketPostLimitCount = intval($this->Settings->Get('t_postlimit'));
		}

		$_ticketPostOrder = 'ASC';
		if ($this->Settings->Get('t_postorder') == 'desc') {
			$_ticketPostOrder = 'DESC';
		}

		if ($_ticketPostOffset < 0) {
			$_ticketPostOffset = 0;

			$_ticketPostLimitCount = $_ticketPostCount;
		}

		$_ticketPostContainer = $_SWIFT_TicketObject->GetTicketPosts($_ticketPostOffset, $_ticketPostLimitCount, $_ticketPostOrder);

		$_participantsContainer = $_participantHTMLContainer = array();
		$_userImageUserIDList = $_staffImageUserIDList = array();
		foreach ($_ticketPostContainer as $_ticketPostID => $_SWIFT_TicketPostObject) {
			if ($_SWIFT->Staff->GetPermission('staff_canviewusers') != '0' && $_SWIFT_TicketPostObject->GetProperty('creator') == SWIFT_Ticket::CREATOR_USER &&
					$_SWIFT_TicketPostObject->GetProperty('userid') != '0' && !in_array($_SWIFT_TicketPostObject->GetProperty('userid'), $_userImageUserIDList)) {
				$_userImageUserIDList[] = $_SWIFT_TicketPostObject->GetProperty('userid');
			} else if ($_SWIFT_TicketPostObject->GetProperty('creator') == SWIFT_Ticket::CREATOR_STAFF &&
					$_SWIFT_TicketPostObject->GetProperty('staffid') != '0' && !in_array($_SWIFT_TicketPostObject->GetProperty('staffid'), $_staffImageUserIDList)) {
				$_staffImageUserIDList[] = $_SWIFT_TicketPostObject->GetProperty('staffid');
			}

			// Participants
			$_userHash = md5($_SWIFT_TicketPostObject->GetProperty('creator') . ':' . $_SWIFT_TicketPostObject->GetProperty('userid') . ':' . $_SWIFT_TicketPostObject->GetProperty('fullname'));
			$_staffHash = md5($_SWIFT_TicketPostObject->GetProperty('creator') . ':' . $_SWIFT_TicketPostObject->GetProperty('staffid') . ':' . $_SWIFT_TicketPostObject->GetProperty('fullname'));
			if ($_SWIFT_TicketPostObject->GetProperty('creator') == SWIFT_TicketPost::CREATOR_USER)
			{
				if (in_array($_userHash, $_participantsContainer))
				{
					continue;
				}

				$_participantHTMLContainer[] = array($this->Language->Get('badgeuser'), $_SWIFT_TicketPostObject->GetProperty('fullname'));

				$_participantsContainer[] = $_userHash;
			} else if ($_SWIFT_TicketPostObject->GetProperty('creator') == SWIFT_TicketPost::CREATOR_STAFF) {
				if (in_array($_staffHash, $_participantsContainer))
				{
					continue;
				}

				$_participantHTMLContainer[] = array($this->Language->Get('badgestaff'), $_SWIFT_TicketPostObject->GetProperty('fullname'));
				$_participantsContainer[] = $_staffHash;

			} else if ($_SWIFT_TicketPostObject->GetProperty('creator') == SWIFT_TicketPost::CREATOR_THIRDPARTY) {
				if (in_array($_userHash, $_participantsContainer))
				{
					continue;
				}

				$_participantHTMLContainer[] = array($this->Language->Get('badgethirdparty'), $_SWIFT_TicketPostObject->GetProperty('fullname'));
				$_participantsContainer[] = $_userHash;

			} else if ($_SWIFT_TicketPostObject->GetProperty('creator') == SWIFT_TicketPost::CREATOR_CC || $_SWIFT_TicketPostObject->GetProperty('creator') == SWIFT_TicketPost::CREATOR_BCC) {
				if (in_array($_userHash, $_participantsContainer))
				{
					continue;
				}

				$_participantHTMLContainer[] = array($this->Language->Get('badgecc'), $_SWIFT_TicketPostObject->GetProperty('fullname'));
				$_participantsContainer[] = $_userHash;

			}
		}

		$_variableContainer = array('_ticketPostOffset' => $_ticketPostOffset, '_ticketPostLimitCount' => $_ticketPostLimitCount, '_ticketPostContainer' => $_ticketPostContainer,
				'_userImageUserIDList' => $_userImageUserIDList, '_staffImageUserIDList' => $_staffImageUserIDList, '_ticketPostCount' => $_ticketPostCount);


		// Ratings
		$_ratingContainer = SWIFT_Rating::Retrieve(array(SWIFT_Rating::TYPE_TICKET), $_SWIFT->Staff, false, $_SWIFT_TicketObject->GetProperty('departmentid'));

		$this->View->RenderInfoBox($_SWIFT_TicketObject, $_SWIFT_UserObject, $_SWIFT_UserOrganizationObject);
		$this->View->RenderParticipantBox($_SWIFT_TicketObject, $_participantHTMLContainer);
		$this->View->RenderWorkflowBox($_SWIFT_TicketObject, $_ticketLinkedTableContainer);

		if ($_SWIFT->Staff->GetPermission('staff_canviewratings') != '0')
		{
			SWIFT_RatingRenderer::RenderNavigationBox(array(SWIFT_Rating::TYPE_TICKET), $_SWIFT_TicketObject->GetTicketID(), '/Tickets/Ticket/Rating/' . $_SWIFT_TicketObject->GetTicketID(), $_ratingContainer);
		}

		$this->UserInterface->AddNavigationBox($this->Language->Get('quickfilter'), SWIFT_TicketViewRenderer::RenderTree($_listType, $_departmentID,
				$_ticketStatusID, $_ticketTypeID));
		$this->UserInterface->Header(sprintf($this->Language->Get('viewticketext'), $_SWIFT_TicketObject->GetTicketDisplayID(), $_SWIFT_TicketObject->GetProperty('subject')),
				self::MENU_ID, self::NAVIGATION_ID);
		$this->View->RenderTicket($_SWIFT_TicketObject, $_SWIFT_UserObject, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset, $_variableContainer);
		$this->UserInterface->Footer();
		return true;
	}

	/**
	 * Print a ticket
	 *
	 * @author Parminder Singh
	 * @param int $_ticketID The Ticket ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 * @throws SWIFT_Exception if the ticket id is empty
	 */

	public function PrintTicket($_ticketID) {
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
			return false;
		}else if (empty($_ticketID)) {

			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		}


		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);
		$_SWIFT_UserObject = $_SWIFT_TicketObject->GetUserObject();
		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
			return false;
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanviewtickets') == '0') {
			throw new SWIFT_Exception(SWIFT_NOPERMISSION);
			return false;

		}
		$_staffCache = $this->Cache->Get('staffcache');
		$_departmentCache = $this->Cache->Get('departmentcache');
		$_ticketStatusCache = $this->Cache->Get('statuscache');
		$_ticketPriorityCache = $this->Cache->Get('prioritycache');
		$_ticketTypeCache = $this->Cache->Get('tickettypecache');

		/*
		 * BUG FIX - Varun Shoor
		 *
		 * SWIFT-1553 The Print function does not print the reply from top even if setting is correct
		 *
		 * Comments: None
		 */

		$_ticketPostOrder = 'ASC';
		if ($this->Settings->Get('t_postorder') == 'desc') {
			$_ticketPostOrder = 'DESC';
		}

		$_ticketPostContainer = $_SWIFT_TicketObject->GetTicketPosts(false, false, $_ticketPostOrder);
		$_ticketPostArray = array();
		foreach ($_ticketPostContainer as $_ticketPostID => $_SWIFT_TicketPostObject) {
			$_ticketPostArray[$_ticketPostID]['fullname'] = StripName(htmlspecialchars($_SWIFT_TicketPostObject->GetProperty('fullname')), 19);
			$_designation = '';
			if ($_SWIFT_TicketPostObject->GetProperty('creator') == SWIFT_TicketPost::CREATOR_STAFF && isset($_staffCache[$_SWIFT_TicketPostObject->GetProperty('staffid')]) && !empty($_staffCache[$_SWIFT_TicketPostObject->GetProperty('staffid')]['designation'])) {
				 $_designation = htmlspecialchars($_staffCache[$_SWIFT_TicketPostObject->GetProperty('staffid')]['designation']);
			}elseif ($_SWIFT_TicketPostObject->GetProperty('creator') == SWIFT_TicketPost::CREATOR_USER && $_SWIFT_UserObject instanceof SWIFT_User && $_SWIFT_UserObject->GetProperty('userdesignation') != '') {
				$_designation = htmlspecialchars($_SWIFT_UserObject->GetProperty('userdesignation'));
			}

			$_ticketPostArray[$_ticketPostID]['designation'] = $_designation;
			if ($_SWIFT_TicketPostObject->GetProperty('isthirdparty') == '1' || $_SWIFT_TicketPostObject->GetProperty('creator') == SWIFT_TicketPost::CREATOR_THIRDPARTY) {
				$_creator = $this->Language->Get('badgethirdparty');
			} else if ($_SWIFT_TicketPostObject->GetProperty('creator') == SWIFT_TicketPost::CREATOR_CC) {
				$_creator = $this->Language->Get('badgecc');
			} else if ($_SWIFT_TicketPostObject->GetProperty('creator') == SWIFT_TicketPost::CREATOR_BCC) {
				$_creator = $this->Language->Get('badgebcc');
			} else if ($_SWIFT_TicketPostObject->GetProperty('creator') == SWIFT_TicketPost::CREATOR_USER) {
				$_creator = $this->Language->Get('badgeuser');
			} else if ($_SWIFT_TicketPostObject->GetProperty('creator') == SWIFT_TicketPost::CREATOR_STAFF) {
				$_creator = $this->Language->Get('badgestaff');
			}
			$_ticketPostArray[$_ticketPostID]['creator'] = $_creator;
			$_ticketPostArray[$_ticketPostID]['contents'] = $_SWIFT_TicketPostObject->GetDisplayContents();
			$_ticketPostArray[$_ticketPostID]['date'] = sprintf($this->Language->Get(IIF($_SWIFT_TicketPostObject->GetProperty('issurveycomment') == '1', 'tppostedonsurvey', 'tppostedon')), SWIFT_Date::Get(SWIFT_Date::TYPE_DATETIME, $_SWIFT_TicketPostObject->GetProperty('dateline')));
		}

		$_departmentTitle = $this->Language->Get('na');
		if ($_SWIFT_TicketObject->GetProperty('departmentid') == '0') {
			$_departmentTitle = $this->Language->Get('trash');
		} else if (isset($_departmentCache[$_SWIFT_TicketObject->GetProperty('departmentid')])) {
			$_departmentTitle = $_departmentCache[$_SWIFT_TicketObject->GetProperty('departmentid')]['title'];
		}

		$_ticketStatusContainer = false;
		if (isset($_ticketStatusCache[$_SWIFT_TicketObject->GetProperty('ticketstatusid')])) {
			$_ticketStatusContainer = $_ticketStatusCache[$_SWIFT_TicketObject->GetProperty('ticketstatusid')];
			$_ticketStatusTitle = $_ticketStatusContainer['title'];
		} else {
			$_ticketStatusTitle = $this->Language->Get('na');
		}

		$_ticketPriorityContainer = false;
		if (isset($_ticketPriorityCache[$_SWIFT_TicketObject->GetProperty('priorityid')])) {
			$_ticketPriorityContainer = $_ticketPriorityCache[$_SWIFT_TicketObject->GetProperty('priorityid')];
			$_ticketPriorityTitle = $_ticketPriorityContainer['title'];
		} else {
			$_ticketPriorityTitle = $this->Language->Get('na');
		}


		$_ticketTypeContainer = false;
		if (isset($_ticketTypeCache[$_SWIFT_TicketObject->GetProperty('tickettypeid')])) {
			$_ticketTypeContainer = $_ticketTypeCache[$_SWIFT_TicketObject->GetProperty('tickettypeid')];
			$_ticketTypeTitle = $_ticketTypeContainer['title'];
		} else {
			$_ticketTypeTitle = $this->Language->Get('na');
		}

		$_ticketOwnerContainer = false;
		if (isset($_staffCache[$_SWIFT_TicketObject->GetProperty('ownerstaffid')])) {
			$_ticketOwnerContainer = $_staffCache[$_SWIFT_TicketObject->GetProperty('ownerstaffid')];
			$_ticketOwnerTitle = $_ticketOwnerContainer['fullname'];
		} else if ($_SWIFT_TicketObject->GetProperty('ownerstaffid') == '0') {
			$_ticketOwnerTitle = $this->Language->Get('unassigned2');
		} else {
			$_ticketOwnerTitle = $this->Language->Get('na');
		}

		$_billingEntries = '';
		if ($_SWIFT_TicketObject->GetProperty('hasbilling') == '1' && $_SWIFT->Staff->GetPermission('staff_tcanviewbilling') != '0') {
			$_totalTimeSpent = $_SWIFT_TicketObject->GetProperty('timeworked');
			$_totalTimeBillable = $_SWIFT_TicketObject->GetProperty('timebilled');
			$_billingEntries = '<div class="ticketbillinginfocontainer">';
			$_billingEntries .= '<img src="' . SWIFT::Get('themepathimages') . 'icon_clock.png' . '" align="absmiddle" border="0" /> ' .
					'<b>' . $this->Language->Get('billtotalworked') . '</b> ' . SWIFT_Date::ColorTime($_totalTimeSpent, false, true) .
					'&nbsp;&nbsp;&nbsp;&nbsp;' .
					'<b>' . $this->Language->Get('billtotalbillable') . '</b> ' . SWIFT_Date::ColorTime($_totalTimeBillable, false, true);
			$_billingEntries .= '</div>';
		}

		$_customFields = $this->CustomFieldRendererStaff->Render(SWIFT_CustomFieldRenderer::TYPE_STATIC, SWIFT_UserInterface::MODE_INSERT, array(SWIFT_CustomFieldGroup::GROUP_STAFFTICKET, SWIFT_CustomFieldGroup::GROUP_USERTICKET, SWIFT_CustomFieldGroup::GROUP_STAFFUSERTICKET), null, $_SWIFT_TicketObject->GetTicketID(), $_SWIFT_TicketObject->GetProperty('departmentid'), true,true);

		$this->Template->Assign('_companyName', SWIFT::Get('companyname'));
		$this->Template->Assign('_ticketID', $_SWIFT_TicketObject->GetTicketDisplayID());
		$this->Template->Assign('_ticketSubject', htmlspecialchars($_SWIFT_TicketObject->GetProperty('subject')));
		$this->Template->Assign('_departmentTitle', $_departmentTitle);
		$this->Template->Assign('_ticketStatusTitle', $_ticketStatusTitle);
		$this->Template->Assign('_ticketPriorityTitle', $_ticketPriorityTitle);
		$this->Template->Assign('_ticketTypeTitle', $_ticketTypeTitle);
		$this->Template->Assign('_ticketOwnerTitle', $_ticketOwnerTitle);
		$this->Template->Assign('_ticketDate', SWIFT_Date::Get(SWIFT_Date::TYPE_DATETIME, $_SWIFT_TicketObject->GetProperty('dateline')));
		$this->Template->Assign('_ticketUpdated', SWIFT_Date::Get(SWIFT_Date::TYPE_DATETIME, $_SWIFT_TicketObject->GetProperty('lastactivity')));
		$this->Template->Assign('_ticketPost', $_ticketPostArray);
		$this->Template->Assign('_customFields', $_customFields);
		$this->Template->Assign('_billingEntries', $_billingEntries);



		$this->Template->Render('printticket');

		return true;
	}

	/**
	 * Delete a ticket post
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param int $_ticketPostID The Ticket Post ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function DeletePost($_ticketID, $_ticketPostID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0) {

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcandeleteticketpost') == '0') {
			$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
			$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
			$this->UserInterface->Footer();

			return false;

		}

		$_SWIFT_TicketPostObject = new SWIFT_TicketPost(new SWIFT_DataID($_ticketPostID));
		// Did the object load up?
		if (!$_SWIFT_TicketPostObject instanceof SWIFT_TicketPost || !$_SWIFT_TicketPostObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		if ($_SWIFT_TicketPostObject->GetProperty('ticketid') != $_SWIFT_TicketObject->GetTicketID() ||
				$_SWIFT->Staff->GetPermission('staff_tcandeleteticketpost') == '0') {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Create Audit Log
		$_logText = sprintf($_SWIFT->Language->Get('al_deleteticketpost'), $_SWIFT_TicketPostObject->GetProperty('fullname'),
				$_SWIFT_TicketPostObject->GetProperty('email'));
		SWIFT_TicketAuditLog::AddToLog($_SWIFT_TicketObject, null, SWIFT_TicketAuditLog::ACTION_DELETETICKETPOST,
				$_logText, SWIFT_TicketAuditLog::VALUE_NONE, 0, '',
				0, '');

		// Activity Log
		SWIFT_StaffActivityLog::AddToLog($_logText,
				SWIFT_StaffActivityLog::ACTION_DELETE, SWIFT_StaffActivityLog::SECTION_TICKETS, SWIFT_StaffActivityLog::INTERFACE_STAFF);

		$_SWIFT_TicketPostObject->Delete();

		$_SWIFT_TicketObject->RebuildProperties();

		$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);

		return true;
	}

	/**
	 * Edit a Ticket Post
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param int $_ticketPostID The Ticket Post ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function EditPost($_ticketID, $_ticketPostID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0) {

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanupaticketpost') == '0') {
			$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
			$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
			$this->UserInterface->Footer();

			return false;

		}

		$_SWIFT_TicketPostObject = new SWIFT_TicketPost(new SWIFT_DataID($_ticketPostID));
		// Did the object load up?
		if (!$_SWIFT_TicketPostObject instanceof SWIFT_TicketPost || !$_SWIFT_TicketPostObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		if ($_SWIFT_TicketPostObject->GetProperty('ticketid') != $_SWIFT_TicketObject->GetTicketID() ||
				$_SWIFT->Staff->GetPermission('staff_tcanupaticketpost') == '0') {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('editpost'), self::MENU_ID, self::NAVIGATION_ID);
		$this->View->RenderEditPost($_SWIFT_TicketObject, $_SWIFT_TicketPostObject, $_listType, $_departmentID,
				$_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);
		$this->UserInterface->Footer();

		return true;
	}


	/**
	 * Edit a ticket post (Submission)
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param int $_ticketPostID The Ticket Post ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function EditPostSubmit($_ticketID, $_ticketPostID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0) {

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanupaticketpost') == '0') {
			$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
			$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
			$this->UserInterface->Footer();

			return false;

		}

		$_SWIFT_TicketPostObject = new SWIFT_TicketPost(new SWIFT_DataID($_ticketPostID));
		// Did the object load up?
		if (!$_SWIFT_TicketPostObject instanceof SWIFT_TicketPost || !$_SWIFT_TicketPostObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		if ($_SWIFT_TicketPostObject->GetProperty('ticketid') != $_SWIFT_TicketObject->GetTicketID() ||
				$_SWIFT->Staff->GetPermission('staff_tcanupaticketpost') == '0') {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		$_SWIFT_TicketPostObject->Update($_POST['postcontents'], $_SWIFT->Staff->GetStaffID());

		// Create Audit Log
		$_logText = sprintf($_SWIFT->Language->Get('al_updateticketpost'), $_SWIFT_TicketPostObject->GetProperty('fullname'),
				$_SWIFT_TicketPostObject->GetProperty('email'));
		SWIFT_TicketAuditLog::AddToLog($_SWIFT_TicketObject, null, SWIFT_TicketAuditLog::ACTION_UPDATETICKETPOST,
				$_logText, SWIFT_TicketAuditLog::VALUE_NONE, 0, '',
				0, '');

		// Activity Log
		SWIFT_StaffActivityLog::AddToLog($_logText,
				SWIFT_StaffActivityLog::ACTION_UPDATE, SWIFT_StaffActivityLog::SECTION_TICKETS, SWIFT_StaffActivityLog::INTERFACE_STAFF);

		$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);

		return true;
	}

	/**
	 * Retrieve an attachment
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param int $_attachmentID The Attachment ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function GetAttachment($_ticketID, $_attachmentID) {

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanviewtickets') == '0') {
			$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
			$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
			$this->UserInterface->Footer();

			return false;

		}

		$_SWIFT_AttachmentObject = new SWIFT_Attachment($_attachmentID);
		// Did the object load up?
		if (!$_SWIFT_AttachmentObject instanceof SWIFT_Attachment || !$_SWIFT_AttachmentObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		if ($_SWIFT_AttachmentObject->GetProperty('ticketid') != $_SWIFT_TicketObject->GetTicketID()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		$_SWIFT_AttachmentObject->Dispatch();

		return true;
	}


	/**
	 * SUBMISSION: General Tab
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function GeneralSubmit($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0) {

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);
		$_SWIFT_TicketObject->SetOldTicketProperties();

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanupdateticket') == '0') {
			$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
			$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
			$this->UserInterface->Footer();

			return false;

		}

		/*
		 * BUG FIX - Nidhi Gupta
		 *
		 * SWIFT-839: Permission to restrict staff from moving tickets to departments they're not assigned to
		 *
		 * Comments: Added check for staff to move tickets in unassigned departments
		 */
		// Update Properties
		if ($_SWIFT->Staff->GetPermission('staff_tcanchangeunassigneddepartment') == '0') {
			if ($_SWIFT_TicketObject->Get('departmentid') != $_POST['gendepartmentid'] && !in_array($_POST['gendepartmentid'], $_SWIFT->Staff->GetAssignedDepartments())) {
				$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
				$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
				$this->UserInterface->Footer();

				return false;
			}
		}

		// Process Tags
		if ($_SWIFT->Staff->GetPermission('staff_canupdatetags') != '0')
		{
			SWIFT_Tag::Process(SWIFT_TagLink::TYPE_TICKET, $_SWIFT_TicketObject->GetTicketID(),
					SWIFT_UserInterface::GetMultipleInputValues('tags'), $_SWIFT->Staff->GetStaffID());
		}

		if (isset($_POST['gendepartmentid']) && !empty($_POST['gendepartmentid'])) {
			$_SWIFT_TicketObject->SetDepartment($_POST['gendepartmentid']);
		}

		if (isset($_POST['genownerstaffid'])) {
			$_SWIFT_TicketObject->SetOwner($_POST['genownerstaffid']);
		}

		if (isset($_POST['gentickettypeid']) && !empty($_POST['gentickettypeid'])) {
			$_SWIFT_TicketObject->SetType($_POST['gentickettypeid']);
		}

		if (isset($_POST['genticketstatusid']) && !empty($_POST['genticketstatusid'])) {
			$_SWIFT_TicketObject->SetStatus($_POST['genticketstatusid']);
		}

		if (isset($_POST['genticketpriorityid']) && !empty($_POST['genticketpriorityid'])) {
			$_SWIFT_TicketObject->SetPriority($_POST['genticketpriorityid']);
		}

		$_SWIFT_TicketObject->ProcessUpdatePool();
		SWIFT_TicketManager::RebuildCache();

		$_SWIFT_TicketObject->ExecuteSLA(false, true, false);

		// Begin Hook: staff_ticket_general
		unset($_hookCode);
		($_hookCode = SWIFT_Hook::Execute('staff_ticket_general')) ? eval($_hookCode) : false;
		// End Hook

		$_SWIFT_TicketViewObject = SWIFT_TicketViewRenderer::GetDefaultTicketViewObject($_departmentID);

		$_nextTicketID = false;
		if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_NEXTTICKET) {
			$_nextTicketID = SWIFT_TicketViewRenderer::GetNextPreviousTicketID($_SWIFT_TicketObject, 'next', $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
		}

		// Does the new department belong to this staff? if not, we need to jump him back to list!
		$_assignedDepartmentIDList = $_SWIFT->Staff->GetAssignedDepartments();
		if (isset($_POST['gendepartmentid']) && !empty($_POST['gendepartmentid']) && !in_array($_POST['gendepartmentid'], $_assignedDepartmentIDList)) {
			$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);

			return true;
		}

		if ($_SWIFT_TicketObject->GetProperty('isresolved') == '1' && $_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_TICKET)
		{
			$GLOBALS['_POST'] = $GLOBALS['_REQUEST'] = $GLOBALS['_GET'] = array();
			/**
			 * BUG FIX: Simaranjit Singh <simaranjit.singh@kayako.com>
			 *
			 * SWIFT-3087: In Internet Explorer, Tickets View page gets garbled when ticket is move to Resolved status.
			 *
			 */
			$GLOBALS['_POST']['isajax'] = true;
			$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);
		} else if ($_SWIFT_TicketObject->GetProperty('isresolved') == '1' && $_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_ACTIVETICKETLIST) {
			$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);

		} else if ($_SWIFT_TicketObject->GetProperty('isresolved') == '1' && $_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_TOPTICKETLIST) {
			$this->Load->Controller('Manage')->Redirect('inbox', -1, -1, -1);

		} else if ($_SWIFT_TicketObject->GetProperty('isresolved') == '1' && $_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_NEXTTICKET) {
			$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
		} else {
			$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);
		}


		return true;
	}


	/**
	 * Flag a Ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param int $_ticketFlagType The Flag Type
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function Flag($_ticketID, $_ticketFlagType, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0) {

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanupdateticket') == '0') {
			$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
			$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
			$this->UserInterface->Footer();

			return false;

		}

		$_SWIFT_TicketFlagObject = new SWIFT_TicketFlag();
		$_ticketFlagContainer = $_SWIFT_TicketFlagObject->GetFlagContainer();
		if (!isset($_ticketFlagContainer[$_ticketFlagType]))
		{
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		$_SWIFT_TicketObject->SetFlag($_ticketFlagType);

		$_SWIFT_TicketObject->ProcessUpdatePool();
		SWIFT_TicketManager::RebuildCache();

		$_SWIFT_TicketObject->ExecuteSLA(false, true, false);

		$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);

		return true;
	}


	/**
	 * Watch a Ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function Watch($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0) {

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanupdateticket') == '0') {
			$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
			$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
			$this->UserInterface->Footer();

			return false;

		}

		$_departmentCache = $this->Cache->Get('departmentcache');
		$_ticketStatusCache = $this->Cache->Get('statuscache');

		$_departmentTitle = $_ticketStatusTitle = '';
		if (isset($_departmentCache[$_SWIFT_TicketObject->GetProperty('departmentid')])) {
			$_departmentTitle = htmlspecialchars($_departmentCache[$_SWIFT_TicketObject->GetProperty('departmentid')]['title']);
		}

		if (isset($_ticketStatusCache[$_SWIFT_TicketObject->GetProperty('ticketstatusid')])) {
			$_ticketStatusTitle = htmlspecialchars($_ticketStatusCache[$_SWIFT_TicketObject->GetProperty('ticketstatusid')]['title']);
		}

		SWIFT_StaffActivityLog::AddToLog(sprintf($_SWIFT->Language->Get('activitywatchticket'),
				htmlspecialchars($_SWIFT_TicketObject->GetProperty('subject')), htmlspecialchars($_departmentTitle),
				htmlspecialchars($_ticketStatusTitle), htmlspecialchars($_SWIFT_TicketObject->GetProperty('fullname'))),
				SWIFT_StaffActivityLog::ACTION_UPDATE, SWIFT_StaffActivityLog::SECTION_TICKETS, SWIFT_StaffActivityLog::INTERFACE_STAFF);

		SWIFT_Ticket::Watch(array($_SWIFT_TicketObject->GetTicketID()), $_SWIFT->Staff);

		$_SWIFT_TicketObject->ProcessUpdatePool();
		SWIFT_TicketManager::RebuildCache();

		// SWIFT-2285 Watching a ticket or adding a ticket watcher resets ticket due time

		$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);

		return true;
	}


	/**
	 * UnWatch a Ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function UnWatch($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0) {

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanupdateticket') == '0') {
			$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
			$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
			$this->UserInterface->Footer();

			return false;

		}

		$_departmentCache = $this->Cache->Get('departmentcache');
		$_ticketStatusCache = $this->Cache->Get('statuscache');

		$_departmentTitle = $_ticketStatusTitle = '';
		if (isset($_departmentCache[$_SWIFT_TicketObject->GetProperty('departmentid')])) {
			$_departmentTitle = htmlspecialchars($_departmentCache[$_SWIFT_TicketObject->GetProperty('departmentid')]['title']);
		}

		if (isset($_ticketStatusCache[$_SWIFT_TicketObject->GetProperty('ticketstatusid')])) {
			$_ticketStatusTitle = htmlspecialchars($_ticketStatusCache[$_SWIFT_TicketObject->GetProperty('ticketstatusid')]['title']);
		}

		SWIFT_StaffActivityLog::AddToLog(sprintf($_SWIFT->Language->Get('activityunwatchticket'),
				htmlspecialchars($_SWIFT_TicketObject->GetProperty('subject')), htmlspecialchars($_departmentTitle),
				htmlspecialchars($_ticketStatusTitle), htmlspecialchars($_SWIFT_TicketObject->GetProperty('fullname'))),
				SWIFT_StaffActivityLog::ACTION_UPDATE, SWIFT_StaffActivityLog::SECTION_TICKETS, SWIFT_StaffActivityLog::INTERFACE_STAFF);

		SWIFT_Ticket::UnWatch(array($_SWIFT_TicketObject->GetTicketID()), $_SWIFT->Staff);

		$_SWIFT_TicketObject->ProcessUpdatePool();
		SWIFT_TicketManager::RebuildCache();

		// SWIFT-2285 Watching a ticket or adding a ticket watcher resets ticket due time

		$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);

		return true;
	}


	/**
	 * Take a Ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function Take($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0) {

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);
		$_SWIFT_TicketObject->SetOldTicketProperties();

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanupdateticket') == '0') {
			$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
			$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
			$this->UserInterface->Footer();

			return false;

		}

		$_departmentCache = $this->Cache->Get('departmentcache');
		$_ticketStatusCache = $this->Cache->Get('statuscache');

		$_departmentTitle = $_ticketStatusTitle = '';
		if (isset($_departmentCache[$_SWIFT_TicketObject->GetProperty('departmentid')])) {
			$_departmentTitle = htmlspecialchars($_departmentCache[$_SWIFT_TicketObject->GetProperty('departmentid')]['title']);
		}

		if (isset($_ticketStatusCache[$_SWIFT_TicketObject->GetProperty('ticketstatusid')])) {
			$_ticketStatusTitle = htmlspecialchars($_ticketStatusCache[$_SWIFT_TicketObject->GetProperty('ticketstatusid')]['title']);
		}

		SWIFT_StaffActivityLog::AddToLog(sprintf($_SWIFT->Language->Get('activitytaketicket'),
				htmlspecialchars($_SWIFT_TicketObject->GetProperty('subject')), htmlspecialchars($_departmentTitle),
				htmlspecialchars($_ticketStatusTitle), htmlspecialchars($_SWIFT_TicketObject->GetProperty('fullname'))),
				SWIFT_StaffActivityLog::ACTION_UPDATE, SWIFT_StaffActivityLog::SECTION_TICKETS, SWIFT_StaffActivityLog::INTERFACE_STAFF);

		$_SWIFT_TicketObject->SetOwner($_SWIFT->Staff->GetStaffID());

		$_SWIFT_TicketObject->ProcessUpdatePool();
		SWIFT_TicketManager::RebuildCache();

		/*
		 * BUG FIX - Abhishek Mittal
		 *
		 * SWIFT-3616 Reply due time should not be reset when flagging a ticket
		 *
		 * Comments: Issue also persists when using "Take"
		 */
		$_SWIFT_TicketObject->ExecuteSLA(false, true, false);

		$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);

		return true;
	}


	/**
	 * Take a Ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function Surrender($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0) {

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);
		$_SWIFT_TicketObject->SetOldTicketProperties();

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanupdateticket') == '0') {
			$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
			$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
			$this->UserInterface->Footer();

			return false;

		}

		$_departmentCache = $this->Cache->Get('departmentcache');
		$_ticketStatusCache = $this->Cache->Get('statuscache');

		$_departmentTitle = $_ticketStatusTitle = '';
		if (isset($_departmentCache[$_SWIFT_TicketObject->GetProperty('departmentid')])) {
			$_departmentTitle = htmlspecialchars($_departmentCache[$_SWIFT_TicketObject->GetProperty('departmentid')]['title']);
		}

		if (isset($_ticketStatusCache[$_SWIFT_TicketObject->GetProperty('ticketstatusid')])) {
			$_ticketStatusTitle = htmlspecialchars($_ticketStatusCache[$_SWIFT_TicketObject->GetProperty('ticketstatusid')]['title']);
		}

		SWIFT_StaffActivityLog::AddToLog(sprintf($_SWIFT->Language->Get('activitysurrenderticket'),
				htmlspecialchars($_SWIFT_TicketObject->GetProperty('subject')), htmlspecialchars($_departmentTitle),
				htmlspecialchars($_ticketStatusTitle), htmlspecialchars($_SWIFT_TicketObject->GetProperty('fullname'))),
				SWIFT_StaffActivityLog::ACTION_UPDATE, SWIFT_StaffActivityLog::SECTION_TICKETS, SWIFT_StaffActivityLog::INTERFACE_STAFF);

		$_SWIFT_TicketObject->SetOwner('0');

		$_SWIFT_TicketObject->ProcessUpdatePool();
		SWIFT_TicketManager::RebuildCache();

		/*
		 * BUG FIX - Abhishek Mittal
		 *
		 * SWIFT-3616 Reply due time should not be reset when flagging a ticket
		 *
		 * Comments: Issue also persists when using "Surrender"
		 */
		$_SWIFT_TicketObject->ExecuteSLA(false, true, false);

		$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);

		return true;
	}

	/**
	 * Render the New Ticket Dialog
	 *
	 * @author Varun Shoor
	 * @param int $_chatObjectID (OPTIONAL) The Chat Object ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function NewTicket($_chatObjectID = false) {
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		// Check permission
		if ($_SWIFT->Staff->GetPermission('staff_tcaninsertticket') == '0') {
			$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('newticket'), self::MENU_ID,
					self::NAVIGATION_ID);
			$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
			$this->UserInterface->Footer();

			return false;

		}

		if (is_numeric($_chatObjectID))
		{
			$_chatObjectID = intval($_chatObjectID);
		} else {
			$_chatObjectID = false;
		}

		$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('newticket'), self::MENU_ID,
				self::NAVIGATION_ID);
		$this->View->RenderNewTicketDialog($_chatObjectID);
		$this->UserInterface->Footer();

		return true;
	}

	/**
	 * Render the New Ticket Form
	 *
	 * @author Varun Shoor
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function NewTicketForm() {
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_templateGroupCache = $this->Cache->Get('templategroupcache');

		$_assignedDepartmentIDList = $_SWIFT->Staff->GetAssignedDepartments();

		// Check permission
		if ($_SWIFT->Staff->GetPermission('staff_tcaninsertticket') == '0') {
			$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('newticket'), self::MENU_ID,
					self::NAVIGATION_ID);
			$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
			$this->UserInterface->Footer();

			return false;

		} else if (!isset($_POST['departmentid']) || !isset($_POST['tickettype']) || empty($_POST['departmentid']) || empty($_POST['tickettype'])) {
			$this->Load->NewTicket();

			return false;
		} else if (!in_array($_POST['departmentid'], $_assignedDepartmentIDList) && $_SWIFT->Settings->Get('t_restrictnewticket') == '1') {
			throw new SWIFT_Exception('No Permission to Department');
		}

		$_finalTicketType = View_Ticket::TAB_NEWTICKET_EMAIL;
		if ($_POST['tickettype'] == 'user')
		{
			$_finalTicketType = View_Ticket::TAB_NEWTICKET_USER;
		}

		/**
		 * ---------------------------------------------
		 * LIVE CHAT INTEGRATION
		 * ---------------------------------------------
		 */

		if (SWIFT_App::IsInstalled(APP_LIVECHAT) && isset($_POST['chatobjectid']) && !empty($_POST['chatobjectid']))
		{
			SWIFT_Loader::LoadModel('Chat:Chat', APP_LIVECHAT);
			SWIFT_Loader::LoadModel('Chat:ChatQueue', APP_LIVECHAT);

			$_SWIFT_ChatObject = false;
			try {
				$_SWIFT_ChatObject = new SWIFT_Chat($_POST['chatobjectid']);
			} catch (SWIFT_Exception $_SWIFT_ExceptionObject) {

			}

			if ($_SWIFT_ChatObject instanceof SWIFT_Chat && $_SWIFT_ChatObject->GetIsClassLoaded() && $_SWIFT_ChatObject->CanAccess($_SWIFT->Staff)) {
				/*
				 * BUG FIX - Varun Shoor
				 *
				 * SWIFT-1428 "Skip User Details" option when used while Tag Generation, throws an error while ticket creation from KD
				 *
				 * Comments: Falls back to staff email address if no user email is present
				 */
				$_userEmailAddress = $_SWIFT_ChatObject->GetProperty('useremail');
				if (empty($_userEmailAddress)) {
					$_userEmailAddress = $_SWIFT->Staff->GetProperty('email');
				}

				// Now attempt to load the data and integrate it into _POST
				$_chatDataArray = $_SWIFT_ChatObject->GetConversationArray();

				$_conversation = $this->Language->Get('ntchatid') . $_SWIFT_ChatObject->GetProcessedChatID() . SWIFT_CRLF;
				$_conversation .= $this->Language->Get('ntchatuserfullname') . $_SWIFT_ChatObject->GetProperty('userfullname') . SWIFT_CRLF;
				$_conversation .= $this->Language->Get('ntchatuseremail') . $_userEmailAddress . SWIFT_CRLF;
				$_conversation .= $this->Language->Get('ntchatstafffullname') . $_SWIFT_ChatObject->GetProperty('staffname') . SWIFT_CRLF;
				$_conversation .= $this->Language->Get('ntchatdepartment') . $_SWIFT_ChatObject->GetProperty('departmenttitle') . SWIFT_CRLF . SWIFT_CRLF;

				foreach ($_chatDataArray as $_val) {
					if ($_val['type'] != SWIFT_ChatQueue::MESSAGE_SYSTEM && $_val['type'] != SWIFT_ChatQueue::MESSAGE_STAFF && $_val['type'] != SWIFT_ChatQueue::MESSAGE_CLIENT) {
						continue;
					}

					if ($this->Settings->Get('livechat_timestamps') == true) {
						$_conversation .= '' . $_val['timestamp'] . ' ';
					}

					if ($_val['type'] == SWIFT_ChatQueue::MESSAGE_SYSTEM) {
						$_conversation .= '* ' . $_val['messagehtml'] . SWIFT_CRLF;
					} else if ($_val['type'] == SWIFT_ChatQueue::MESSAGE_STAFF || $_val['type'] == SWIFT_ChatQueue::MESSAGE_CLIENT) {
						$_conversation .= $_val['name'] . ': ' . $_val['messagehtml'] . SWIFT_CRLF;
					}
				}

				$_POST['newticketsubject'] = $_SWIFT_ChatObject->GetProperty('subject');
				$_POST['newticketcontents'] = $_conversation;
				$_POST['containertaginput_newticketto'] = array($_userEmailAddress);

				// Do we need to load up the user?
				if ($_POST['tickettype'] == 'user' && $_SWIFT_ChatObject->GetProperty('chattype') == SWIFT_Chat::CHATTYPE_CLIENT) {
					$_SWIFT_UserObject = false;
					if ($_SWIFT_ChatObject->GetProperty('userid') != '0') {
						// Attempt to load the user
						try {
							$_SWIFT_UserObject = new SWIFT_User(new SWIFT_DataID($_SWIFT_ChatObject->GetProperty('userid')));
						} catch (SWIFT_Exception $_SWIFT_ExceptionObject) {

							return false;
						}
					}

					// Couldnt load user from ID? attempt to load it from email
					if (!$_SWIFT_UserObject instanceof SWIFT_User || !$_SWIFT_UserObject->GetIsClassLoaded()) {
						// Do we have a valid template group?
						$_userGroupID = false;

						if (isset($_templateGroupCache[$_SWIFT_ChatObject->GetProperty('tgroupid')])) {
							$_userGroupID = $_templateGroupCache[$_SWIFT_ChatObject->GetProperty('tgroupid')]['regusergroupid'];

							// Go through the master group
						} else {
							$_masterTemplateGroupID = SWIFT_TemplateGroup::GetDefaultGroupID();
							$_userGroupID = $_templateGroupCache[$_masterTemplateGroupID]['regusergroupid'];
						}

						if (empty($_userGroupID)) {
							throw new SWIFT_Exception('Invalid User Group ID');
						}

						$_userID = SWIFT_Ticket::GetOrCreateUserID($_SWIFT_ChatObject->GetProperty('userfullname'), $_userEmailAddress, $_userGroupID, false, false);

						$_POST['userid'] = $_SWIFT_ChatObject->GetProperty('userfullname');
						$_POST['autocomplete_userid'] = $_userID;
					} else {
						$_POST['userid'] = $_SWIFT_UserObject->GetProperty('fullname');
						$_POST['autocomplete_userid'] = $_SWIFT_UserObject->GetUserID();
					}
				}
			}
		}


		$this->UserInterface->AddNavigationBox($this->Language->Get('quickfilter'), SWIFT_TicketViewRenderer::RenderTree('inbox', -1, -1, -1));
		$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('newticket'), self::MENU_ID,
				self::NAVIGATION_ID);
		$this->View->RenderNewTicket($_finalTicketType, intval($_POST['departmentid']));
		$this->UserInterface->Footer();

		return true;
	}

	/**
	 * Render the Billing tab for this Ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function Billing($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0) {
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}


		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff)) {
			echo $this->Language->Get('msgnoperm');

			return false;

		}

		SWIFT::Set('ticketurlsuffix', $_listType . '/' . $_departmentID . '/' . $_ticketStatusID . '/' . $_ticketTypeID . '/' . $_ticketLimitOffset);

		$this->View->RenderBilling($_SWIFT_TicketObject, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);

		return true;
	}

	/**
	 * Render the Billing tab for user
	 *
	 * @author Varun Shoor
	 * @param int $_userID The User ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function BillingUser($_userID) {
		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_SWIFT_UserObject = new SWIFT_User(new SWIFT_DataID($_userID));

		// Did the object load up?
		if (!$_SWIFT_UserObject instanceof SWIFT_User || !$_SWIFT_UserObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		$this->View->RenderBillingUser($_SWIFT_UserObject);

		return true;
	}

	/**
	 * Check to see if its a valid billing time (hh:mm)
	 *
	 * @author Varun Shoor
	 * @param string $_billingTime Check Billing Time
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If Invalid Data is Provided
	 */
	static protected function IsValidBillingTime($_billingTime)
	{
		$_SWIFT = SWIFT::GetInstance();

		$_matches = array();

		if (!preg_match('@([\d]{2}):([\d]{2})@', $_billingTime, $_matches))
		{
			return false;
		}

		if (!intval($_matches[1]) && !intval($_matches[2]))
		{
			return false;
		}

		return true;
	}

	/**
	 * Parse hh:mm and retrieve time in seconds
	 *
	 * @author Varun Shoor
	 * @param string $_billingTime Check Billing Time
	 * @return int The Billing Seconds
	 * @throws SWIFT_Exception If Invalid Data is Provided
	 */
	static protected function GetBillingTime($_billingTime)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!self::IsValidBillingTime($_billingTime))
		{
			return 0;
		}

		if (!strpos($_billingTime, ':'))
		{
			return 0;
		}

		$_timeContainer = explode(':', $_billingTime);
		if (count($_timeContainer) != 2)
		{
			return 0;
		}

		$_timeHours = intval($_timeContainer[0]);
		$_timeMinutes = intval($_timeContainer[1]);

		$_finalSeconds = 0;
		$_finalSeconds += $_timeHours * 3600;
		$_finalSeconds += $_timeMinutes * 60;

		return $_finalSeconds;
	}

	/**
	 * Render the Release tab for this Ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function BillingSubmit($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0) {
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}


		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcaninsertbilling') == '0') {
			echo $this->Language->Get('msgnoperm');

			return false;

		}

		// Try to load worker staff object
		$_SWIFT_StaffObject_Worker = new SWIFT_Staff(new SWIFT_DataID($_POST['billingworkerstaffid']));
		if (!$_SWIFT_StaffObject_Worker instanceof SWIFT_Staff || !$_SWIFT_StaffObject_Worker->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		$_workDateline = GetDateFieldTimestamp('billworkdate');
		$_billDateline = GetDateFieldTimestamp('billdate');

		if (empty($_POST['billingworkerstaffid']))
		{
			$this->UserInterface->Error($this->Language->Get('titlefieldempty'), $this->Language->Get('msgfieldempty'));
		} else if (empty($_workDateline) || empty($_billDateline)) {
			$this->UserInterface->Error($this->Language->Get('titleinvalidbilldate'), $this->Language->Get('msginvalidbilldate'));
		} else {
			// Create the time worked entry
			$_SWIFT_TicketTimeTrackObject = SWIFT_TicketTimeTrack::Create($_SWIFT_TicketObject, $_SWIFT->Staff,
					self::GetBillingTime($_POST['billingtimeworked']), self::GetBillingTime($_POST['billingtimebillable']),
					$_POST['notecolor_billingnotes'], $_POST['billingnotes'], $_SWIFT_StaffObject_Worker, $_workDateline, $_billDateline);

			// Update Custom Field Values
			$this->CustomFieldManager->Update(SWIFT_CustomFieldManager::MODE_POST, SWIFT_UserInterface::MODE_INSERT,
					array(SWIFT_CustomFieldGroup::GROUP_TIMETRACK), SWIFT_CustomFieldManager::CHECKMODE_STAFF, $_SWIFT_TicketTimeTrackObject->GetTicketTimeTrackID());
		}

		// Begin Hook: staff_ticket_billing
		unset($_hookCode);
		($_hookCode = SWIFT_Hook::Execute('staff_ticket_billing')) ? eval($_hookCode) : false;
		// End Hook

		$_SWIFT_TicketObject->ProcessUpdatePool();
		SWIFT_TicketManager::RebuildCache();

		SWIFT_TicketAuditLog::AddToLog($_SWIFT_TicketObject, null, SWIFT_TicketAuditLog::ACTION_UPDATETICKET,
				$_SWIFT->Language->Get('al_ticketbilling'),
				SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');

		/*
		 * BUG FIX - Varun Shoor
		 *
		 * SWIFT-1102 Due time is being set again, if ticket updated with billing time
		 *
		 * Comments: Not required
		 */
//		$_SWIFT_TicketObject->ExecuteSLA();

		$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);

		return true;
	}

	/**
	 * Edit a billing entry
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param int $_ticketTimeTrackID The Ticket Time Track ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function EditBilling($_ticketID, $_ticketTimeTrackID)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (empty($_ticketID)) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		} else if ($_SWIFT->Staff->GetPermission('staff_tcanupdatebilling') == '0') {
			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff)) {
			echo $this->Language->Get('msgnoperm');

			return false;

		}

		$_SWIFT_TicketTimeTrackObject = new SWIFT_TicketTimeTrack(new SWIFT_DataID($_ticketTimeTrackID));
		if (!$_SWIFT_TicketTimeTrackObject instanceof SWIFT_TicketTimeTrack || !$_SWIFT_TicketTimeTrackObject->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		}

		$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('editbilling'), self::MENU_ID, self::NAVIGATION_ID);
		$this->View->RenderBillingForm(SWIFT_UserInterface::MODE_EDIT, $_SWIFT_TicketObject, $_SWIFT_TicketTimeTrackObject);
		$this->UserInterface->Footer();

		return true;
	}

	/**
	 * Edit a billing entry processor
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param int $_ticketTimeTrackID The Ticket Time Track ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function EditBillingSubmit($_ticketID, $_ticketTimeTrackID)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (empty($_ticketID)) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		} else if ($_SWIFT->Staff->GetPermission('staff_tcanupdatebilling') == '0') {
			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff)) {
			echo $this->Language->Get('msgnoperm');

			return false;
		}

		$_SWIFT_TicketTimeTrackObject = new SWIFT_TicketTimeTrack(new SWIFT_DataID($_ticketTimeTrackID));
		if (!$_SWIFT_TicketTimeTrackObject instanceof SWIFT_TicketTimeTrack || !$_SWIFT_TicketTimeTrackObject->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		}

		// Try to load worker staff object
		$_SWIFT_StaffObject_Worker = new SWIFT_Staff(new SWIFT_DataID($_POST['ebillingworkerstaffid']));
		if (!$_SWIFT_StaffObject_Worker instanceof SWIFT_Staff || !$_SWIFT_StaffObject_Worker->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		$_workDateline = GetDateFieldTimestamp('ebillworkdate');
		$_billDateline = GetDateFieldTimestamp('ebilldate');

		if (trim($_POST['ebillingtimeworked']) == '' || trim($_POST['ebillingtimebillable']) == '' || empty($_POST['ebillingworkerstaffid']))
		{
			$this->UserInterface->DisplayError($this->Language->Get('titlefieldempty'), $this->Language->Get('msgfieldempty'));
		} else if (empty($_workDateline) || empty($_billDateline)) {
			$this->UserInterface->DisplayError($this->Language->Get('titleinvalidbilldate'), $this->Language->Get('msginvalidbilldate'));
		} else {
			$_SWIFT_TicketTimeTrackObject->Update(self::GetBillingTime($_POST['ebillingtimeworked']), self::GetBillingTime($_POST['ebillingtimebillable']),
					$_POST['notecolor_ebillingnotes'], $_POST['ebillingnotes'], $_SWIFT_StaffObject_Worker, $_workDateline, $_billDateline, $_SWIFT->Staff);

		}

		/*
		 * BUG FIX - Varun Shoor
		 *
		 * SWIFT-722 Modified Billing entry does not get updated on the ticket
		 *
		 * Comments: Rebuild the properties
		 */
		$_SWIFT_TicketObject->RebuildProperties();

		$_SWIFT_TicketObject->ProcessUpdatePool();
		SWIFT_TicketManager::RebuildCache();

		SWIFT_TicketAuditLog::AddToLog($_SWIFT_TicketObject, null, SWIFT_TicketAuditLog::ACTION_UPDATETICKET,
				$_SWIFT->Language->Get('al_updticketbilling'),
				SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');

		// Update Custom Field Values
		$this->CustomFieldManager->Update(SWIFT_CustomFieldManager::MODE_POST, SWIFT_UserInterface::MODE_EDIT,
				array(SWIFT_CustomFieldGroup::GROUP_TIMETRACK), SWIFT_CustomFieldManager::CHECKMODE_STAFF, $_SWIFT_TicketTimeTrackObject->GetTicketTimeTrackID());

		$_SWIFT_TicketObject->RebuildProperties();

		/**
		 * BUG FIX - Ravi Sharma <ravi.sharma@kayako.com>
		 *
		 * SWIFT-3191: After editing a single custom field under ‘Ticket Time Tracking’ section, all other custom field entries display same updated value.
		 *
		 * Comments: Emptying the global requests in order to avoid reuse.
		 */
		$GLOBALS['_POST']           = $GLOBALS['_REQUEST'] = $GLOBALS['_GET'] = array();
		$GLOBALS['_POST']['isajax'] = true;

		echo $this->View->RenderBillingEntries($_SWIFT_TicketObject);

		return true;
	}

	/**
	 * Delete Billing Processer
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param int $_ticketTimeTrackID The Ticket Time Track ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function DeleteBilling($_ticketID, $_ticketTimeTrackID)
	{
		$_SWIFT = SWIFT::GetInstance();
		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (empty($_ticketID)) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		} else if ($_SWIFT->Staff->GetPermission('staff_tcandeletebilling') == '0') {
			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff)) {
			echo $this->Language->Get('msgnoperm');

			return false;

		}

		$_SWIFT_TicketTimeTrackObject = new SWIFT_TicketTimeTrack(new SWIFT_DataID($_ticketTimeTrackID));
		if (!$_SWIFT_TicketTimeTrackObject instanceof SWIFT_TicketTimeTrack || !$_SWIFT_TicketTimeTrackObject->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		}

		$_SWIFT_TicketTimeTrackObject->Delete();

		echo $this->View->RenderBillingEntries($_SWIFT_TicketObject);

		$_SWIFT_TicketObject->RebuildProperties();

		SWIFT_TicketAuditLog::AddToLog($_SWIFT_TicketObject, null, SWIFT_TicketAuditLog::ACTION_UPDATETICKET,
			$_SWIFT->Language->Get('al_delbilling'),
			SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');

		return true;
	}

	/**
	 * Render the Forward tab for this Ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function Forward($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0) {
		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanforward') == '0') {
			echo $this->Language->Get('msgnoperm');

			return false;

		}

		$_SWIFT_UserObject = $_SWIFT_TicketObject->GetUserObject();

		SWIFT::Set('ticketurlsuffix', $_listType . '/' . $_departmentID . '/' . $_ticketStatusID . '/' . $_ticketTypeID . '/' . $_ticketLimitOffset);

		$this->View->RenderForward($_SWIFT_TicketObject, $_SWIFT_UserObject, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID,
			$_ticketLimitOffset);

		return true;
	}

	/**
	 * Render the FollowUp tab for this Ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @param int $_prefix (OPTIONAL) Whether its an inline display
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function FollowUp($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0, $_prefix = '') {
		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanfollowup') == '0') {
			echo $this->Language->Get('msgnoperm');

			return false;

		}

		$_SWIFT_UserObject = $_SWIFT_TicketObject->GetUserObject();

		$_finalPrefix = 'fu';
		$_isInline = false;
		if (!empty($_prefix) && strlen($_prefix) == '2')
		{
			$_finalPrefix = $_prefix;
			$_isInline = true;
		}

		$this->View->RenderFollowUp($_SWIFT_TicketObject, $_SWIFT_UserObject, $_finalPrefix, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID,
			$_ticketLimitOffset, $_isInline);

		return true;
	}

	/**
	 * Follow-Up Submission Processor
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function FollowUpSubmit($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0) {
		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanfollowup') == '0') {
			echo $this->Language->Get('msgnoperm');

			return false;

		}

		/*
		 * BUG FIX - Nidhi Gupta
		 *
		 * SWIFT-839: Permission to restrict staff from moving tickets to departments they're not assigned to
		 *
		 * Comments: Added check for staff to move tickets in unassigned departments
		 */
		if ($_SWIFT->Staff->GetPermission('staff_tcanchangeunassigneddepartment') == '0') {
			if ($_SWIFT_TicketObject->Get('departmentid') != $_POST['fudepartmentid'] && !in_array($_POST['fudepartmentid'], $_SWIFT->Staff->GetAssignedDepartments())) {
				$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
				$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
				$this->UserInterface->Footer();

				return false;
			}
		}

		$this->_ProcessFollowUp($_SWIFT_TicketObject, 'fu');

		// Begin Hook: staff_ticket_followup
		unset($_hookCode);
		($_hookCode = SWIFT_Hook::Execute('staff_ticket_followup')) ? eval($_hookCode) : false;
		// End Hook

		SWIFT_TicketManager::RebuildCache();

		SWIFT_TicketAuditLog::AddToLog($_SWIFT_TicketObject, null, SWIFT_TicketAuditLog::ACTION_UPDATETICKET,
			$_SWIFT->Language->Get('al_createfollowup'),
			SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');

		// Activity Log
		SWIFT_StaffActivityLog::AddToLog($_SWIFT->Language->Get('al_createfollowup'),
				SWIFT_StaffActivityLog::ACTION_UPDATE, SWIFT_StaffActivityLog::SECTION_TICKETS, SWIFT_StaffActivityLog::INTERFACE_STAFF);

		/**
		 * BUG FIX - Ravi Sharma
		 *
		 * SWIFT-3151: Due time gets reset when follow up is added on ticket.
		 *
		 * Comments: None.
		 */
		if (isset($_POST['fudochangeproperties']))
		{
			$_SWIFT_TicketObject->ExecuteSLA(false, true, false);
		}

		$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);

		return true;
	}

	/**
	 * Delete Follow-Up Processer
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param int $_ticketFollowUpID The Ticket FollowUp ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function DeleteFollowUp($_ticketID, $_ticketFollowUpID)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (empty($_ticketID)) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		} else if ($_SWIFT->Staff->GetPermission('staff_tcandeletefollowup') == '0') {
			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff)) {
			echo $this->Language->Get('msgnoperm');

			return false;

		}

		$_SWIFT_TicketFollowUpObject = new SWIFT_TicketFollowUp(new SWIFT_DataID($_ticketFollowUpID));
		if (!$_SWIFT_TicketFollowUpObject instanceof SWIFT_TicketFollowUp || !$_SWIFT_TicketFollowUpObject->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		}

		$_SWIFT_TicketFollowUpObject->Delete();

		$_SWIFT_TicketObject->RebuildProperties();

		SWIFT_TicketAuditLog::AddToLog($_SWIFT_TicketObject, null, SWIFT_TicketAuditLog::ACTION_UPDATETICKET,
			$_SWIFT->Language->Get('al_delfollowup'),
			SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');

		$this->Load->Method('View', $_ticketID);

		return true;
	}

	/**
	 * Render the Release tab for this Ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function Release($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0) {
		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanrelease') == '0') {
			echo $this->Language->Get('msgnoperm');

			return false;

		}

		$_SWIFT_UserObject = $_SWIFT_TicketObject->GetUserObject();

		$this->View->RenderRelease($_SWIFT_TicketObject, $_SWIFT_UserObject, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID,
			$_ticketLimitOffset);

		return true;
	}

	/**
	 * Render the Release tab for this Ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function ReleaseSubmit($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0) {
		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanrelease') == '0') {
			echo $this->Language->Get('msgnoperm');

			return false;

		}

		$_SWIFT_UserObject = $_SWIFT_TicketObject->GetUserObject();

		/*
		 * BUG FIX - Nidhi Gupta
		 *
		 * SWIFT-839: Permission to restrict staff from moving tickets to departments they're not assigned to
		 *
		 * Comments: Added check for staff to move tickets in unassigned departments
		 */
		if ($_SWIFT->Staff->GetPermission('staff_tcanchangeunassigneddepartment') == '0') {
			if ($_SWIFT_TicketObject->Get('departmentid') != $_POST['reldepartmentid'] && !in_array($_POST['reldepartmentid'], $_SWIFT->Staff->GetAssignedDepartments())) {
				$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
				$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
				$this->UserInterface->Footer();

				return false;
			}
		}

		// Process Tags
		if ($_SWIFT->Staff->GetPermission('staff_canupdatetags') != '0')
		{
			SWIFT_Tag::Process(SWIFT_TagLink::TYPE_TICKET, $_SWIFT_TicketObject->GetTicketID(),
					SWIFT_UserInterface::GetMultipleInputValues('reltags'), $_SWIFT->Staff->GetStaffID());
		}

		// Update Properties
		if (isset($_POST['reldepartmentid']) && !empty($_POST['reldepartmentid'])) {
			$_SWIFT_TicketObject->SetDepartment($_POST['reldepartmentid']);
		}

		if (isset($_POST['relownerstaffid'])) {
			$_SWIFT_TicketObject->SetOwner($_POST['relownerstaffid']);
		}

		if (isset($_POST['reltickettypeid']) && !empty($_POST['reltickettypeid'])) {
			$_SWIFT_TicketObject->SetType($_POST['reltickettypeid']);
		}

		if (isset($_POST['relticketstatusid']) && !empty($_POST['relticketstatusid'])) {
			$_SWIFT_TicketObject->SetStatus($_POST['relticketstatusid']);
		}

		if (isset($_POST['relticketpriorityid']) && !empty($_POST['relticketpriorityid'])) {
			$_SWIFT_TicketObject->SetPriority($_POST['relticketpriorityid']);
		}

		if (isset($_POST['releaseticketnotes']) && trim($_POST['releaseticketnotes']) != '') {
			/*
			 * BUG FIX - Varun Shoor
			 *
			 * SWIFT-738 New ticket notification does not work if the note is added from the Release tab
			 *
			 * Comments: Trigger notification event
			 */

			$_SWIFT_TicketObject->NotificationManager->SetEvent('newticketnotes');

			$_staffName = $_SWIFT->Staff->GetProperty('fullname');
			$_staffEmail = $_SWIFT->Staff->GetProperty('email');

			$_SWIFT_TicketObject->SetWatcherProperties($_staffName, sprintf($_SWIFT->Language->Get('watcherprefix'), $_staffName, $_staffEmail) . SWIFT_CRLF . $_POST['releaseticketnotes']);

			$_SWIFT_TicketObject->CreateNote($_SWIFT_UserObject, $_POST['releaseticketnotes'], $_POST['notecolor_releaseticketnotes'], $_POST['releasenotetype']);
		}

		$_dueDateline = GetDateFieldTimestamp('releasedue');
		$_resolutionDueDateline = GetDateFieldTimestamp('releaseresolutiondue');

		// Due Dateline
		if (!empty($_dueDateline) && gmdate('d M Y h:i A', $_dueDateline) != gmdate('d M Y h:i A', $_SWIFT_TicketObject->GetProperty('duetime'))) {
			$_SWIFT_TicketObject->SetDue($_dueDateline);

		// We need to clear it?
		} else if (empty($_dueDateline) && $_SWIFT_TicketObject->GetProperty('duetime') != '0') {
			$_SWIFT_TicketObject->ClearOverdue();
		}

		// Resolution Due Dateline
		if (!empty($_resolutionDueDateline) && gmdate('d M Y h:i A', $_resolutionDueDateline) != gmdate('d M Y h:i A', $_SWIFT_TicketObject->GetProperty('resolutionduedateline'))) {
			$_SWIFT_TicketObject->SetResolutionDue($_resolutionDueDateline);

		// We need to clear it?
		} else if (empty($_resolutionDueDateline) && $_SWIFT_TicketObject->GetProperty('resolutionduedateline') != '0') {
			$_SWIFT_TicketObject->ClearResolutionDue();
		}

		// Time tracking stuff
		if (!empty($_POST['relbillingtimeworked']) || !empty($_POST['relbillingtimebillable']))
		{
			// Create the time worked entry
			$_SWIFT_TicketTimeTrackObject = SWIFT_TicketTimeTrack::Create($_SWIFT_TicketObject, $_SWIFT->Staff,
					self::GetBillingTime($_POST['relbillingtimeworked']), self::GetBillingTime($_POST['relbillingtimebillable']),
					1, '', $_SWIFT->Staff, DATENOW, DATENOW);
		}

		// Begin Hook: staff_ticket_release
		unset($_hookCode);
		($_hookCode = SWIFT_Hook::Execute('staff_ticket_release')) ? eval($_hookCode) : false;
		// End Hook

		$_SWIFT_TicketObject->ProcessUpdatePool();
		$_SWIFT_TicketObject->RebuildProperties();
		SWIFT_TicketManager::RebuildCache();

		$_SWIFT_TicketViewObject = SWIFT_TicketViewRenderer::GetDefaultTicketViewObject($_departmentID);

		$_nextTicketID = false;
		if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_NEXTTICKET) {
			$_nextTicketID = SWIFT_TicketViewRenderer::GetNextPreviousTicketID($_SWIFT_TicketObject, 'next', $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
		}

		$_SWIFT_TicketObject->ExecuteSLA(false, true, false);

		// Does the new department belong to this staff? if not, we need to jump him back to list!
		$_assignedDepartmentIDList = $_SWIFT->Staff->GetAssignedDepartments();
		if (isset($_POST['resdepartmentid']) && !empty($_POST['resdepartmentid']) && !in_array($_POST['resdepartmentid'], $_assignedDepartmentIDList)) {
			$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
		} else {
			if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_TICKET)
			{
				$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);
			} else if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_ACTIVETICKETLIST) {
				$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);

			} else if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_TOPTICKETLIST) {
				$this->Load->Controller('Manage')->Redirect('inbox', -1, -1, -1);

			} else if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_NEXTTICKET) {
				if (!empty($_nextTicketID))
				{
					$this->Load->Method('View', $_nextTicketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);
				} else {
					$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
				}
			}
		}

		return true;
	}

	/**
	 * Render the Edit tab for this Ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function Edit($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0) {
		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanupdateticket') == '0') {
			echo $this->Language->Get('msgnoperm');

			return false;

		}

		$this->View->RenderEdit($_SWIFT_TicketObject, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);

		return true;
	}

	/**
	 * Edit Tab Submission
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function EditSubmit($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0) {
		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanupdateticket') == '0') {
			echo $this->Language->Get('msgnoperm');

			return false;

		}

		/**
		* BUG FIX: Parminder Singh
		*
		* SWIFT-1745: Regular expression during editing custom field
		*
		* Comments: Added Custom Field Check
		*/

		$_customFieldCheckResult = $this->CustomFieldManager->Check(SWIFT_CustomFieldManager::MODE_POST, SWIFT_UserInterface::MODE_EDIT,
				array(SWIFT_CustomFieldGroup::GROUP_STAFFTICKET, SWIFT_CustomFieldGroup::GROUP_USERTICKET, SWIFT_CustomFieldGroup::GROUP_STAFFUSERTICKET), SWIFT_CustomFieldManager::CHECKMODE_STAFF, $_SWIFT_TicketObject->GetProperty('departmentid'));
		if ($_customFieldCheckResult[0] == false)
		{
			SWIFT::Alert($this->Language->Get('titlefieldempty'), $this->Language->Get('msgfieldempty'));

			$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);

			return false;
		}

		/*
		 * BUG FIX - Varun Shoor
		 *
		 * SWIFT-590 Changes made to the user details in Staff CP are not effective (even though the Staff CP shows the updated information)
		 * SWIFT-953 User Organization does not get updated while changing the user details in ticket
		 *
		 * Comments: Changing the original fix because it did not have a provision for creating users in case one didnt exist.
		 */
		$_userGroupID = SWIFT_UserGroup::RetrieveDefaultUserGroupID(SWIFT_UserGroup::TYPE_REGISTERED);

		/*
		 * BUG FIX - Varun Shoor
		 *
		 * SWIFT-1434 Editing and adding a space in the ticket recipient field of a ticket, help desk fails to read the address and shows a blank page while reply
		 *
		 * Comments: None
		 */
		$_editEmail = trim($_POST['editemail']);
		if (!IsEmailValid($_editEmail)) {
			$_editEmail = $_SWIFT_TicketObject->GetProperty('email');
		}

		// Update Properties
		$_SWIFT_TicketObject->Update($_POST['editsubject'], $_POST['editfullname'], $_editEmail);

		/*
		 * BUG FIX - Simaranjit Singh
		 *
		 * SWIFT-2759: Error when editing tickets and further bug with creating user accounts
		 *
		 * Comments: None
		 */
		$_userID = SWIFT_Ticket::GetOrCreateUserID($_editEmail, $_editEmail, $_userGroupID);

		/*
		 * BUG FIX - Varun Shoor
		 *
		 * SWIFT-1864 After editing the full name of a ticket from the Edit tab, it still shows the old full name of user on ticket.
		 *
		 */
		SWIFT_TicketPost::UpdateFullnameAndEmailOnTicketUser($_SWIFT_TicketObject->GetTicketID(), $_SWIFT_TicketObject->GetProperty('userid'), $_userID, $_POST['editfullname'], $_editEmail);

		if (!empty($_userID) && $_userID != $_SWIFT_TicketObject->GetProperty('userid')) {
			$_SWIFT_TicketObject->UpdateUser($_userID);
		}

		// Update the Ticket SLA Plan
		if ($_POST['editticketslaplanid'] != $_SWIFT_TicketObject->GetProperty('ticketslaplanid') && $_POST['editticketslaplanid'] != '0') {
			try {
				$_SWIFT_SLAPlanObject = new SWIFT_SLA(new SWIFT_DataID($_POST['editticketslaplanid']));

				$_SWIFT_TicketObject->SetSLA($_SWIFT_SLAPlanObject);
			} catch (SWIFT_Exception $_SWIFT_ExceptionObject) {

				return false;
			}
		} else if ($_POST['editticketslaplanid'] == '0' && $_SWIFT_TicketObject->GetProperty('ticketslaplanid') != '0') {
			$_SWIFT_TicketObject->ClearSLA();
		}

		// Update Recipients
		SWIFT_TicketRecipient::DeleteOnTicket(array($_SWIFT_TicketObject->GetTicketID()));

		$_thirdPartyEmailContainer = self::GetSanitizedEmailList('editthirdparty');
		$_ccEmailContainer = self::GetSanitizedEmailList('editcc');
		$_bccEmailContainer = self::GetSanitizedEmailList('editbcc');

		if (_is_array($_thirdPartyEmailContainer)) {
			SWIFT_TicketRecipient::Create($_SWIFT_TicketObject, SWIFT_TicketRecipient::TYPE_THIRDPARTY, $_thirdPartyEmailContainer);
		}

		if (_is_array($_ccEmailContainer)) {
			SWIFT_TicketRecipient::Create($_SWIFT_TicketObject, SWIFT_TicketRecipient::TYPE_CC, $_ccEmailContainer);
		}

		if (_is_array($_bccEmailContainer)) {
			SWIFT_TicketRecipient::Create($_SWIFT_TicketObject, SWIFT_TicketRecipient::TYPE_BCC, $_bccEmailContainer);
		}

		// Update Custom Field Values
		$this->CustomFieldManager->Update(SWIFT_CustomFieldManager::MODE_POST, SWIFT_UserInterface::MODE_EDIT,
				array(SWIFT_CustomFieldGroup::GROUP_STAFFTICKET, SWIFT_CustomFieldGroup::GROUP_USERTICKET, SWIFT_CustomFieldGroup::GROUP_STAFFUSERTICKET),
				SWIFT_CustomFieldManager::CHECKMODE_STAFF, $_SWIFT_TicketObject->GetTicketID(), $_SWIFT_TicketObject->GetProperty('departmentid'));

		$_SWIFT_TicketObject->ProcessUpdatePool();

		/*
 		* BUG FIX - Ravi Sharma
 		*
 		* SWIFT-3212 Due time resets on updating the ticket from edit tab
 		*
 		* Comments: None
 		*/
		if ($_SWIFT_TicketObject->GetProperty('isresolved') != '1')
		{
			/*
			 * Bug Fix - Mansi Wason
			 *
			 * SWIFT- 3835 "Incorrect SLA plan gets linked with the ticket when ticket is moved from a resolved status to unresolved status."
			 *
			 * comment - By clicking on 'Edit' tab and without making any changes if we 'Update' the ticket. This will lead to reset of the 'Reply Due' time which should not be the case.
			 */

			$_SWIFT_TicketObject->ExecuteSLA(false, true, false);
		}

		// Do we have to merge it?
		if (!empty($_POST['mergeticketid'])) {
			$_SWIFT_TicketObject_Merge = false;
			$_POST['mergeticketid'] = Clean($_POST['mergeticketid']);
			if (is_numeric($_POST['mergeticketid'])) {
				$_SWIFT_TicketObject_Merge = new SWIFT_Ticket(new SWIFT_DataID($_POST['mergeticketid']));
			} else {
				$_ticketID_Merge = SWIFT_Ticket::GetTicketIDFromMask($_POST['mergeticketid']);
				if (!empty($_ticketID_Merge)) {
					$_SWIFT_TicketObject_Merge = new SWIFT_Ticket(new SWIFT_DataID($_ticketID_Merge));
				}
			}

			if ($_SWIFT_TicketObject_Merge instanceof SWIFT_Ticket && $_SWIFT_TicketObject_Merge->GetIsClassLoaded()) {
				SWIFT_Ticket::Merge(array($_SWIFT_TicketObject->GetTicketID()), $_SWIFT_TicketObject_Merge->GetTicketID(), $_SWIFT->Staff->GetStaffID());
				SWIFT::Info($this->Language->Get('titleeditmergesuccess'), $this->Language->Get('msgeditmergesuccess'));

				$_ticketID = $_SWIFT_TicketObject_Merge->GetTicketID();
				$_departmentID = $_SWIFT_TicketObject_Merge->GetProperty('departmentid');
				$_ticketStatusID = $_SWIFT_TicketObject_Merge->GetProperty('ticketstatusid');
				$_ticketTypeID = $_SWIFT_TicketObject_Merge->GetProperty('tickettypeid');
				$_ticketLimitOffset = -1;
			} else {
				SWIFT::Alert($this->Language->Get('titleeditmergefailed'), $this->Language->Get('msgeditmergefailed'));
			}
		}

		// Begin Hook: staff_ticket_edit
		unset($_hookCode);
		($_hookCode = SWIFT_Hook::Execute('staff_ticket_edit')) ? eval($_hookCode) : false;
		// End Hook

		SWIFT_TicketManager::RebuildCache();

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2392: While adding more than one CC email address in a ticket, CC users list do not get updated in ticket
		 *
		 * Comments: $_POST, $_REQUEST and $_GET contains old values so making them empty
		 */
		$GLOBALS['_POST'] = $GLOBALS['_REQUEST'] = $GLOBALS['_GET'] = array();
		$GLOBALS['_POST']['isajax'] = true;

		$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);

		return true;
	}

	/**
	 * Retrieve the Sanitized Email List
	 *
	 * @author Varun Shoor
	 *
	 * @param string $_fieldName The Field Name
	 * @param bool   $_isCheckbox
	 *
	 * @return array
	 */
	static protected function GetSanitizedEmailList($_fieldName, $_isCheckbox = false) {
		$_SWIFT = SWIFT::GetInstance();

		$_emailContainer = array();

		$_postEmailValues = SWIFT_UserInterface::GetMultipleInputValues($_fieldName, $_isCheckbox);
		if (_is_array($_postEmailValues))
		{
			foreach ($_postEmailValues as $_key => $_val)
			{
				if (IsEmailValid($_val))
				{
					$_emailContainer[] = $_val;
				}
			}
		}
		return $_emailContainer;
	}

	/**
	 * Render the Audit Log for this Ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function AuditLog($_ticketID) {
		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanviewauditlog') == '0') {
			echo $this->Language->Get('msgnoperm');

			return false;

		}

		$this->View->RenderAuditLog($_SWIFT_TicketObject);

		return true;
	}

	/**
	 * Render the History for this Ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function History($_ticketID) {
		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanviewtickets') == '0') {
			echo $this->Language->Get('msgnoperm');

			return false;

		}

		$this->View->RenderHistory($_SWIFT_TicketObject);

		return true;
	}

	/**
	 * Render the History for this Ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function HistoryUser($_userID) {
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_SWIFT_UserObject = new SWIFT_User(new SWIFT_DataID($_userID));

		// Did the object load up?
		if (!$_SWIFT_UserObject instanceof SWIFT_User || !$_SWIFT_UserObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		$this->View->RenderHistory($_SWIFT_UserObject);

		return true;
	}

	/**
	 * Render the History for this Ticket based on a list of emails
	 *
	 * @author Varun Shoor
	 * @param string $_baseData The Base64 Encoded Data
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function HistoryEmails($_baseData) {
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_finalEmailList = array();

		parse_str(base64_decode($_baseData), $_dataContainer);

		if (isset($_dataContainer['email']) && _is_array($_dataContainer['email']))
		{
			foreach ($_dataContainer['email'] as $_email)
			{
				if (IsEmailValid($_email) && !in_array($_email, $_finalEmailList))
				{
					$_finalEmailList[] = $_email;
				}
			}
		}

		$this->View->RenderHistory($_finalEmailList);

		return true;
	}

	/**
	 * Render the Add Note form for this Ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function AddNote($_ticketID) {
		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcaninsertticketnote') == '0') {
			echo $this->Language->Get('msgnoperm');

			return false;
		}

		$_SWIFT_UserObject = $_SWIFT_TicketObject->GetUserObject();

		$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('addnote'), self::MENU_ID, self::NAVIGATION_ID);
		$this->View->RenderNoteForm(SWIFT_UserInterface::MODE_INSERT, $_SWIFT_TicketObject, null, $_SWIFT_UserObject);
		$this->UserInterface->Footer();

		return true;
	}

	/**
	 * Render the Add Note form for this Ticket
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function AddNoteSubmit($_ticketID) {
		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcaninsertticketnote') == '0') {
			echo $this->Language->Get('msgnoperm');

			return false;
		}

		$_SWIFT_UserObject = $_SWIFT_TicketObject->GetUserObject();

		// Notification Event
		$_SWIFT_TicketObject->NotificationManager->SetEvent('newticketnotes');

		$_staffName = $_SWIFT->Staff->GetProperty('fullname');
		$_staffEmail = $_SWIFT->Staff->GetProperty('email');

		$_SWIFT_TicketObject->SetWatcherProperties($_staffName, sprintf($_SWIFT->Language->Get('watcherprefix'), $_staffName, $_staffEmail) . SWIFT_CRLF . $_POST['ticketnotes']);

		$_forStaffID = false;
		if (isset($_POST['forstaffid'])) {
			$_forStaffID = intval($_POST['forstaffid']);
		}

		if (isset($_POST['ticketnotes']) && trim($_POST['ticketnotes']) != '') {
			$_SWIFT_TicketObject->CreateNote($_SWIFT_UserObject, $_POST['ticketnotes'], $_POST['notecolor_ticketnotes'], $_POST['notetype'], $_forStaffID);
		}

		echo $this->View->RenderNotes($_SWIFT_TicketObject, $_SWIFT_UserObject);

		return true;
	}

	/**
	 * Edit a note
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param int $_ticketNoteID The Ticket Note ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function EditNote($_ticketID, $_ticketNoteID)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (empty($_ticketID)) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		} else if ($_SWIFT->Staff->GetPermission('staff_tcanupdateticketnote') == '0') {
			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff)) {
			echo $this->Language->Get('msgnoperm');

			return false;

		}

		$_SWIFT_TicketNoteObject = new SWIFT_TicketNote($_ticketNoteID);
		if (!$_SWIFT_TicketNoteObject instanceof SWIFT_TicketNote || !$_SWIFT_TicketNoteObject->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		}

		$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('editnote'), self::MENU_ID, self::NAVIGATION_ID);
		$this->View->RenderNoteForm(SWIFT_UserInterface::MODE_EDIT, $_SWIFT_TicketObject, $_SWIFT_TicketNoteObject);
		$this->UserInterface->Footer();

		return true;
	}

	/**
	 * Edit a note processor
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param int $_ticketNoteID The Ticket Note ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function EditNoteSubmit($_ticketID, $_ticketNoteID)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (empty($_ticketID)) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		} else if ($_SWIFT->Staff->GetPermission('staff_tcanupdateticketnote') == '0') {
			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff)) {
			echo $this->Language->Get('msgnoperm');

			return false;
		}

		$_SWIFT_TicketNoteObject = new SWIFT_TicketNote($_ticketNoteID);
		if (!$_SWIFT_TicketNoteObject instanceof SWIFT_TicketNote || !$_SWIFT_TicketNoteObject->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		}

		// Edit notes
		if (trim($_POST['ticketnotes']) != '')
		{
			$_SWIFT_TicketNoteObject->Update($_SWIFT->Staff->GetStaffID(), $_SWIFT->Staff->GetProperty('fullname'), $_POST['ticketnotes'], intval($_POST['notecolor_ticketnotes']));
		}

		$_SWIFT_UserObject = $_SWIFT_TicketObject->GetUserObject();

		echo $this->View->RenderNotes($_SWIFT_TicketObject, $_SWIFT_UserObject);

		SWIFT_TicketAuditLog::AddToLog($_SWIFT_TicketObject, null, SWIFT_TicketAuditLog::ACTION_NEWNOTE,
			$_SWIFT->Language->Get('al_updatenote'),
			SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');

		return true;
	}

	/**
	 * Delete Note Processer
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param int $_ticketNoteID The Ticket Note ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function DeleteNote($_ticketID, $_ticketNoteID)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (empty($_ticketID)) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		} else if ($_SWIFT->Staff->GetPermission('staff_tcandeleteticketnote') == '0') {
			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff)) {
			echo $this->Language->Get('msgnoperm');

			return false;

		}

		$_SWIFT_TicketNoteObject = new SWIFT_TicketNote($_ticketNoteID);
		if (!$_SWIFT_TicketNoteObject instanceof SWIFT_TicketNote || !$_SWIFT_TicketNoteObject->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		}


		$_SWIFT_TicketNoteObject->Delete();

		$_SWIFT_UserObject = $_SWIFT_TicketObject->GetUserObject();

		echo $this->View->RenderNotes($_SWIFT_TicketObject, $_SWIFT_UserObject);

		$_SWIFT_TicketObject->RebuildProperties();

		SWIFT_TicketAuditLog::AddToLog($_SWIFT_TicketObject, null, SWIFT_TicketAuditLog::ACTION_NEWNOTE,
			$_SWIFT->Language->Get('al_deletenote'),
			SWIFT_TicketAuditLog::VALUE_NONE, 0, '', 0, '');

		return true;
	}

	/**
	 * Execute a workflow action
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param int $_ticketWorkflowID The Ticket Workflow ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function ExecuteWorkflow($_ticketID, $_ticketWorkflowID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1,
			$_ticketTypeID = -1, $_ticketLimitOffset = 0)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (empty($_ticketID)) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		} else if ($_SWIFT->Staff->GetPermission('staff_tcanworkflow') == '0') {
			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff)) {
			echo $this->Language->Get('msgnoperm');

			return false;
		}

		// Attempt to load the workflow object
		$_SWIFT_TicketWorkflowObject = new SWIFT_TicketWorkflow(new SWIFT_DataID($_ticketWorkflowID));
		if (!$_SWIFT_TicketWorkflowObject instanceof SWIFT_TicketWorkflow || !$_SWIFT_TicketWorkflowObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		$_ticketLinkedTableContainer = SWIFT_TicketLinkedTable::RetrieveOnTicket($_SWIFT_TicketObject);

		// Make sure this workflow is available to the current ticket
		$_proceedWithWorkflow = false;
		if (isset($_ticketLinkedTableContainer[SWIFT_TicketLinkedTable::LINKTYPE_WORKFLOW])) {
			foreach ($_ticketLinkedTableContainer[SWIFT_TicketLinkedTable::LINKTYPE_WORKFLOW] as $_ticketLinkedTableID => $_ticketLinkedTableValue) {
				if ($_ticketLinkedTableValue['linktypeid'] == $_ticketWorkflowID) {
					$_proceedWithWorkflow = true;
				}
			}
		}

		if ($_proceedWithWorkflow) {
			$_SWIFT_TicketWorkflowObject->ExecuteActions($_SWIFT_TicketObject);
		}

		$_SWIFT_TicketObject->ProcessUpdatePool();
		SWIFT_TicketManager::RebuildCache();
		$_SWIFT_TicketObject->ExecuteSLA(false, true, false);

		// Trash?
		if ($_SWIFT_TicketObject->GetProperty('departmentid') == '0') {
			$_departmentID = 0;
			$_ticketStatusID = -1;
			$_ticketTypeID = -1;

		// Department Changed?
		} else if ($_SWIFT_TicketObject->GetProperty('departmentid') != $_departmentID && $_departmentID != -1) {
			$_departmentID = intval($_SWIFT_TicketObject->GetProperty('departmentid'));
			$_ticketStatusID = -1;
			$_ticketTypeID = -1;
		}

		$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);

		// Execute notifications
		if ($_proceedWithWorkflow) {
			$_workflowNotificationContainer = SWIFT_TicketWorkflowNotification::RetrieveOnWorkflow($_ticketWorkflowID);
			foreach ($_workflowNotificationContainer as $_ticketWorkflowNotificationID => $_ticketWorkflowNotificationContainer) {
				$_notificationSubject = $_ticketWorkflowNotificationContainer['subject'];
				$_notificationContents = $_ticketWorkflowNotificationContainer['notificationcontents'];

				$_notificationType = false;
				switch ($_ticketWorkflowNotificationContainer['notificationtype']) {
					case SWIFT_TicketWorkflowNotification::TYPE_USER:
						$_notificationType = SWIFT_TicketNotification::TYPE_USER;
						break;

					case SWIFT_TicketWorkflowNotification::TYPE_USERORGANIZATION:
						$_notificationType = SWIFT_TicketNotification::TYPE_USERORGANIZATION;
						break;

					case SWIFT_TicketWorkflowNotification::TYPE_STAFF:
						$_notificationType = SWIFT_TicketNotification::TYPE_STAFF;
						break;

					case SWIFT_TicketWorkflowNotification::TYPE_TEAM:
						$_notificationType = SWIFT_TicketNotification::TYPE_TEAM;
						break;

					case SWIFT_TicketWorkflowNotification::TYPE_DEPARTMENT:
						$_notificationType = SWIFT_TicketNotification::TYPE_DEPARTMENT;
						break;

					default:
						break;
				}

				$_SWIFT_TicketObject->Notification->Dispatch($_notificationType, array(), $_notificationSubject, $_notificationContents);
			}
		}

		return true;
	}

	/**
	 * Ticket Jump Processor (Prev/Next)
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function Jump($_jumpType, $_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (empty($_ticketID)) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		} else if ($_SWIFT->Staff->GetPermission('staff_tcanviewtickets') == '0') {
			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff)) {
			echo $this->Language->Get('msgnoperm');

			return false;
		}

		$_SWIFT_TicketViewObject = SWIFT_TicketViewRenderer::GetDefaultTicketViewObject($_departmentID);

		$_jumpTicketID = 0;
		if ($_jumpType == 'next')
		{
			$_jumpTicketID = SWIFT_TicketViewRenderer::GetNextPreviousTicketID($_SWIFT_TicketObject, 'next', $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
		} else {
			$_jumpTicketID = SWIFT_TicketViewRenderer::GetNextPreviousTicketID($_SWIFT_TicketObject, 'previous', $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
		}

		if (!empty($_jumpTicketID))
		{
			$this->Load->Method('View', $_jumpTicketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);
		} else {
			$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
		}

		return true;
	}

	/**
	 * Ticket Reply Submission Processor
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function ReplySubmit($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (empty($_ticketID)) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		} else if ($_SWIFT->Staff->GetPermission('staff_tcanreply') == '0') {
			return false;
		}

		$_emailQueueCache = $this->Cache->Get('queuecache');
		$_templateGroupCache = $this->Cache->Get('templategroupcache');

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff)) {
			echo $this->Language->Get('msgnoperm');

			return false;
		}

		/*
		 * BUG FIX - Nidhi Gupta
		 *
		 * SWIFT-839: Permission to restrict staff from moving tickets to departments they're not assigned to
		 *
		 * Comments: Added check for staff to move tickets in unassigned departments
		 */
		if ($_SWIFT->Staff->GetPermission('staff_tcanchangeunassigneddepartment') == '0') {
			if ((isset($_POST['replydepartmentid']) && !in_array($_POST['replydepartmentid'], $_SWIFT->Staff->GetAssignedDepartments()))
				|| (isset($_POST['redepartmentid']) && !in_array($_POST['redepartmentid'], $_SWIFT->Staff->GetAssignedDepartments())))
			{
				$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
				$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
				$this->UserInterface->Footer();

				return false;
			}
		}

		$_SWIFT_TicketViewObject = SWIFT_TicketViewRenderer::GetDefaultTicketViewObject($_departmentID);

		$_nextTicketID = false;
		if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_NEXTTICKET) {
			$_nextTicketID = SWIFT_TicketViewRenderer::GetNextPreviousTicketID($_SWIFT_TicketObject, 'next', $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
		}

		$_dontSendEmail = false;
		if (!isset($_POST['optreply_sendemail']) || (isset($_POST['optreply_sendmail']) && $_POST['optreply_sendmail'] != '1'))
		{
			$_dontSendEmail = true;
		}

		$_isPrivate = false;
		if (isset($_POST['optreply_private']) && $_POST['optreply_private'] == '1')
		{
			$_dontSendEmail = true;
			$_isPrivate = true;
		}

		$_isHTML = SWIFT_HTML::DetectHTMLContent($_POST['replycontents']);

		$_fromEmailAddress = self::_GetDispatchFromEmail('reply');
		$_emailQueueID = 0;
		if (isset($_POST['replyfrom']) && $_POST['replyfrom'] > 0 && isset($_emailQueueCache['list'][$_POST['replyfrom']]))
		{
			$_emailQueueID = $_POST['replyfrom'];
		}

		$_SWIFT_TicketObject->UpdateQueue($_emailQueueID);

		$_SWIFT_TicketPostObject = false;
		if (isset($_POST['replycontents']) && trim($_POST['replycontents']) != '' && (!isset($_POST['optreply_createasuser']) || $_POST['optreply_createasuser'] == '0'))
		{
			$_SWIFT_TicketPostObject = SWIFT_TicketPost::CreateStaff($_SWIFT_TicketObject, $_SWIFT->Staff, SWIFT_Ticket::CREATIONMODE_STAFFCP, $_POST['replycontents'],
					'', $_dontSendEmail, $_isHTML, $_fromEmailAddress, $_isPrivate);
			$_ticketPostID = $_SWIFT_TicketPostObject->GetTicketPostID();

		} else if (isset($_POST['replycontents']) && trim($_POST['replycontents']) != '' && isset($_POST['optreply_createasuser']) && $_POST['optreply_createasuser'] == '1') {

			$_emailQueueID = $_SWIFT_TicketObject->GetProperty('emailqueueid');

			$_emailQueueContainer = false;
			if (isset($_emailQueueCache['list'][$_emailQueueID]))
			{
				$_emailQueueContainer = $_emailQueueCache['list'][$_emailQueueID];
			}

			$_templateGroupID = SWIFT_TemplateGroup::GetDefaultGroupID();

			if (_is_array($_emailQueueContainer) && isset($_templateGroupCache[$_emailQueueContainer['tgroupid']]))
			{
				$_templateGroupID = $_emailQueueContainer['tgroupid'];
			}

			$_templateGroupContainer = $_templateGroupCache[$_templateGroupID];

			$_SWIFT_UserObject = $_SWIFT_TicketObject->GetUserObject();
			if (!$_SWIFT_UserObject instanceof SWIFT_User || !$_SWIFT_UserObject->GetIsClassLoaded())
			{
				$_userID = SWIFT_Ticket::GetOrCreateUserID($_SWIFT_TicketObject->GetProperty('fullname'), $_SWIFT_TicketObject->GetProperty('email'), $_templateGroupContainer['regusergroupid']);
				$_SWIFT_TicketObject->UpdateUser($_userID);
				$_SWIFT_UserObject = new SWIFT_User(new SWIFT_DataID($_userID));
			}

			$_ticketPostID = SWIFT_TicketPost::CreateClient($_SWIFT_TicketObject, $_SWIFT_UserObject, SWIFT_Ticket::CREATIONMODE_STAFFCP,
					$_POST['replycontents'], '', SWIFT_TicketPost::CREATOR_USER, $_isHTML, false, array());
			$_SWIFT_TicketPostObject = new SWIFT_TicketPost(new SWIFT_DataID($_ticketPostID));
		}
		/**
		 * BUG FIX : Nidhi Gupta <nidhi.gupta@kayako.com>
		 *
		 * SWIFT-3020 Survey Email arrives first followed by ticket reply.
		 *
		 * Comments: Code placement changes.
		 */
		$this->_ProcessDispatchTab($_SWIFT_TicketObject, 'reply');

		SWIFT_TicketPostLock::DeleteOnTicket(array($_SWIFT_TicketObject->GetTicketID()), $_SWIFT->Staff->GetStaffID());

		if ($_SWIFT_TicketPostObject instanceof SWIFT_TicketPost && isset($_POST['optreply_createasuser']) && $_POST['optreply_createasuser'] == '1')
		{
			$_SWIFT_TicketObject->ProcessPostAttachments($_SWIFT_TicketPostObject, 'replyattachments');
		}

		if (isset($_POST['optreply_watch']) && $_POST['optreply_watch'] == '1')
		{
			SWIFT_Ticket::Watch(array($_SWIFT_TicketObject->GetTicketID()), $_SWIFT->Staff);
		} else {
			SWIFT_Ticket::UnWatch(array($_SWIFT_TicketObject->GetTicketID()), $_SWIFT->Staff);
		}

		$this->_ProcessFollowUp($_SWIFT_TicketObject, 're');

		// Begin Hook: staff_ticket_reply
		unset($_hookCode);
		($_hookCode = SWIFT_Hook::Execute('staff_ticket_reply')) ? eval($_hookCode) : false;
		// End Hook

		if ($_isPrivate == false)
		{
			$_SWIFT_TicketObject->ProcessUpdatePool();
			SWIFT_TicketManager::RebuildCache();
			/**
			 * BUG FIX - Ravi Sharma
			 *
			 * SWIFT-3333: Due time gets reapplied while replying the ticket, if Due time is already cleared from the ticket
			 *
			 * Comments: None.
			 */
			if($_SWIFT_TicketObject->GetProperty('duetime') != '0')
			{
				$_SWIFT_TicketObject->ExecuteSLA(false, true, false);
			}
		}


		// Activity Log
		SWIFT_StaffActivityLog::AddToLog(sprintf($_SWIFT->Language->Get('log_newreply'), $_SWIFT_TicketObject->GetTicketDisplayID()),
				SWIFT_StaffActivityLog::ACTION_UPDATE, SWIFT_StaffActivityLog::SECTION_TICKETS, SWIFT_StaffActivityLog::INTERFACE_STAFF);

		// Do we need to add a macro
		$_addMacro = false;
		if (isset($_POST['optreply_addmacro']) && $_POST['optreply_addmacro'] == '1' && $_SWIFT_TicketPostObject instanceof SWIFT_TicketPost && $_SWIFT_TicketPostObject->GetIsClassLoaded())
		{
			$_addMacro = true;
		}

		// Do we need to add a KB article
		$_addKBArticle = false;
		if (isset($_POST['optreply_addkb']) && $_POST['optreply_addkb'] == '1' && $_SWIFT_TicketPostObject instanceof SWIFT_TicketPost && $_SWIFT_TicketPostObject->GetIsClassLoaded() && SWIFT_App::IsInstalled(APP_KNOWLEDGEBASE))
		{
			$_addKBArticle = true;
		}

		// Does the new department belong to this staff? if not, we need to jump him back to list!
		$_assignedDepartmentIDList = $_SWIFT->Staff->GetAssignedDepartments();
		if (isset($_POST['replydepartmentid']) && !empty($_POST['replydepartmentid']) && !in_array($_POST['replydepartmentid'], $_assignedDepartmentIDList)) {
			if ($_addMacro)
			{
				$this->Load->Controller('MacroReply')->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_addKBArticle);
			} else if ($_addKBArticle) {
				$this->Load->Controller('Article', APP_KNOWLEDGEBASE)->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
			} else {
				$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
			}

			return true;
		}

		if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_TICKET)
		{
			if ($_addMacro)
			{
				$this->Load->Controller('MacroReply')->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, 'viewticket', $_departmentID, $_ticketStatusID, $_ticketTypeID, $_addKBArticle);
			} else if ($_addKBArticle) {
				$this->Load->Controller('Article', APP_KNOWLEDGEBASE)->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, 'viewticket', $_departmentID, $_ticketStatusID, $_ticketTypeID);
			} else {
				$GLOBALS['_POST'] = $GLOBALS['_REQUEST'] = $GLOBALS['_GET'] = array();
				$GLOBALS['_POST']['isajax'] = true;

				$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);
			}
		} else if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_ACTIVETICKETLIST) {
			if ($_addMacro)
			{
				$this->Load->Controller('MacroReply')->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_addKBArticle);
			} else if ($_addKBArticle) {
				$this->Load->Controller('Article', APP_KNOWLEDGEBASE)->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
			} else {
				$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
			}

		} else if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_TOPTICKETLIST) {
			if ($_addMacro)
			{
				$this->Load->Controller('MacroReply')->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, 'inbox', -1, -1, -1, $_addKBArticle);
			} else if ($_addKBArticle) {
				$this->Load->Controller('Article', APP_KNOWLEDGEBASE)->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, 'inbox', -1, -1, -1);
			} else {
				$this->Load->Controller('Manage')->Redirect('inbox', -1, -1, -1);
			}

		} else if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_NEXTTICKET) {
			if (!empty($_nextTicketID))
			{
				$GLOBALS['_POST'] = $GLOBALS['_REQUEST'] = $GLOBALS['_GET'] = array();
				$GLOBALS['_POST']['isajax'] = true;

				$this->Load->Method('View', $_nextTicketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);
			} else {
				$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
			}
		}

		return true;
	}

	/**
	 * Ticket Forward Submission Processor
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function ForwardSubmit($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (empty($_ticketID)) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		} else if ($_SWIFT->Staff->GetPermission('staff_tcanforward') == '0') {
			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff)) {
			echo $this->Language->Get('msgnoperm');

			return false;
		}

		/*
		 * BUG FIX - Nidhi Gupta
		 *
		 * SWIFT-839: Permission to restrict staff from moving tickets to departments they're not assigned to
		 *
		 * Comments: Added check for staff to move tickets in unassigned departments
		 */
		if ($_SWIFT->Staff->GetPermission('staff_tcanchangeunassigneddepartment') == '0') {
			if ((isset($_POST['forwarddepartmentid']) && !in_array($_POST['forwarddepartmentid'], $_SWIFT->Staff->GetAssignedDepartments()))
				|| (isset($_POST['frdepartmentid']) && !in_array($_POST['frdepartmentid'], $_SWIFT->Staff->GetAssignedDepartments())))
			{
				$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('viewticket'), self::MENU_ID,
					self::NAVIGATION_ID);
				$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));
				$this->UserInterface->Footer();

				return false;
			}
		}

		$_SWIFT_TicketViewObject = SWIFT_TicketViewRenderer::GetDefaultTicketViewObject($_departmentID);

		$_nextTicketID = false;
		if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_NEXTTICKET) {
			$_nextTicketID = SWIFT_TicketViewRenderer::GetNextPreviousTicketID($_SWIFT_TicketObject, 'next', $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
		}

		$_destinationEmailContainer = self::GetSanitizedEmailList('forwardto');
		if (!_is_array($_destinationEmailContainer))
		{
			$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);

			return false;
		}

		$_destinationEmailAddress = $_destinationEmailContainer[0];

		$this->_ProcessDispatchTab($_SWIFT_TicketObject, 'forward');

		$_ticketRecipientContainer = SWIFT_TicketRecipient::RetrieveOnTicket($_SWIFT_TicketObject);
		if ((!isset($_ticketRecipientContainer[SWIFT_TicketRecipient::TYPE_THIRDPARTY]) ||
				(isset($_ticketRecipientContainer[SWIFT_TicketRecipient::TYPE_THIRDPARTY]) && !in_array($_destinationEmailAddress, $_ticketRecipientContainer[SWIFT_TicketRecipient::TYPE_THIRDPARTY])))
				&& isset($_POST['optforward_addrecipients']) && is_array($_POST['optforward_addrecipients']) && in_array($_destinationEmailAddress, $_POST['optforward_addrecipients']))
		{
			SWIFT_TicketRecipient::Create($_SWIFT_TicketObject, SWIFT_TicketRecipient::TYPE_THIRDPARTY, array($_destinationEmailAddress));
		}

		$_dontSendEmail = false;
		if (!isset($_POST['optforward_sendemail']) || (isset($_POST['optforward_sendmail']) && $_POST['optforward_sendmail'] != '1'))
		{
			$_dontSendEmail = true;
		}

		$_isPrivate = false;
		if (isset($_POST['optforward_private']) && $_POST['optforward_private'] == '1')
		{
			$_dontSendEmail = true;
			$_isPrivate = true;
		}

		$_isHTML = false;

		$_fromEmailAddress = self::_GetDispatchFromEmail('forward');

		$_emailQueueCache = $_SWIFT->Cache->Get('queuecache');
		$_emailQueueID = 0;
		if ($_POST['forwardfrom'] > 0 && isset($_emailQueueCache['list'][$_POST['forwardfrom']]))
		{
			$_emailQueueID = $_POST['forwardfrom'];
		}

		$_SWIFT_TicketObject->UpdateQueue($_emailQueueID);

		$_SWIFT_TicketPostObject = false;
		if ($_POST['forwardcontents'] != '')
		{
			/*
			* BUG FIX - Ravi Sharma
			*
			* SWIFT-3402 Edit Subject Field option should be available on ticket forwarding page.
			*/
			$_ticketPostID = SWIFT_TicketPost::CreateForward($_SWIFT_TicketObject, $_SWIFT->Staff, SWIFT_Ticket::CREATIONMODE_STAFFCP, $_POST['forwardcontents'], $_POST['forwardsubject'], $_destinationEmailAddress, false, $_isHTML, $_fromEmailAddress, $_isPrivate);

			$_SWIFT_TicketPostObject = new SWIFT_TicketPost(new SWIFT_DataID($_ticketPostID));
		}

		if (isset($_POST['optforward_watch']) && $_POST['optforward_watch'] == '1')
		{
			SWIFT_Ticket::Watch(array($_SWIFT_TicketObject->GetTicketID()), $_SWIFT->Staff);
		} else {
			SWIFT_Ticket::UnWatch(array($_SWIFT_TicketObject->GetTicketID()), $_SWIFT->Staff);
		}

		$this->_ProcessFollowUp($_SWIFT_TicketObject, 'fr');

		// Begin Hook: staff_ticket_forward
		unset($_hookCode);
		($_hookCode = SWIFT_Hook::Execute('staff_ticket_forward')) ? eval($_hookCode) : false;
		// End Hook

		if ($_isPrivate == false)
		{
			$_SWIFT_TicketObject->ProcessUpdatePool();
			SWIFT_TicketManager::RebuildCache();
		}


		// Activity Log
		SWIFT_StaffActivityLog::AddToLog(sprintf($_SWIFT->Language->Get('log_forward'), $_SWIFT_TicketObject->GetTicketDisplayID(), $_destinationEmailAddress),
				SWIFT_StaffActivityLog::ACTION_UPDATE, SWIFT_StaffActivityLog::SECTION_TICKETS, SWIFT_StaffActivityLog::INTERFACE_STAFF);

		// Do we need to add a macro
		$_addMacro = false;
		if (isset($_POST['optforward_addmacro']) && $_POST['optforward_addmacro'] == '1' && $_SWIFT_TicketPostObject instanceof SWIFT_TicketPost && $_SWIFT_TicketPostObject->GetIsClassLoaded())
		{
			$_addMacro = true;
		}

		// Do we need to add a KB article
		$_addKBArticle = false;
		if (isset($_POST['optforward_addkb']) && $_POST['optforward_addkb'] == '1' && $_SWIFT_TicketPostObject instanceof SWIFT_TicketPost && $_SWIFT_TicketPostObject->GetIsClassLoaded() && SWIFT_App::IsInstalled(APP_KNOWLEDGEBASE))
		{
			$_addKBArticle = true;
		}

		// Does the new department belong to this staff? if not, we need to jump him back to list!
		$_assignedDepartmentIDList = $_SWIFT->Staff->GetAssignedDepartments();
		if (isset($_POST['forwarddepartmentid']) && !empty($_POST['forwarddepartmentid']) && !in_array($_POST['forwarddepartmentid'], $_assignedDepartmentIDList)) {
			if ($_addMacro)
			{
				$this->Load->Controller('MacroReply')->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_addKBArticle);
			} else if ($_addKBArticle) {
				$this->Load->Controller('Article', APP_KNOWLEDGEBASE)->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
			} else {
				$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
			}

			return true;
		}

		if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_TICKET)
		{
			if ($_addMacro)
			{
				$this->Load->Controller('MacroReply')->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, 'viewticket', $_departmentID, $_ticketStatusID, $_ticketTypeID, $_addKBArticle);
			} else if ($_addKBArticle) {
				$this->Load->Controller('Article', APP_KNOWLEDGEBASE)->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, 'viewticket', $_departmentID, $_ticketStatusID, $_ticketTypeID);
			} else {
				$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);
			}
		} else if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_ACTIVETICKETLIST) {
			if ($_addMacro)
			{
				$this->Load->Controller('MacroReply')->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_addKBArticle);
			} else if ($_addKBArticle) {
				$this->Load->Controller('Article', APP_KNOWLEDGEBASE)->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
			} else {
				$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
			}

		} else if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_TOPTICKETLIST) {
			if ($_addMacro)
			{
				$this->Load->Controller('MacroReply')->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, 'inbox', '-1', '-1', '-1', $_addKBArticle);
			} else if ($_addKBArticle) {
				$this->Load->Controller('Article', APP_KNOWLEDGEBASE)->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, 'inbox', '-1', '-1', '-1');
			} else {
				$this->Load->Controller('Manage')->Redirect('inbox', -1, -1, -1);
			}

		} else if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_NEXTTICKET) {
			if (!empty($_nextTicketID))
			{
				$this->Load->Method('View', $_nextTicketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);
			} else {
				$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
			}

		}



		return true;
	}

	/**
	 * Retrieve the From Email Address for Dispatch Tab
	 *
	 * @author Varun Shoor
	 * @param string $_tabType The Tab Type
	 * @return string The From Email Address
	 * @throws SWIFT_Exception If Invalid Data is Provided
	 */
	static protected function _GetDispatchFromEmail($_tabType)
	{
		$_SWIFT = SWIFT::GetInstance();

		$_fromEmailAddress = '';

		$_emailQueueCache = $_SWIFT->Cache->Get('queuecache');

		if (isset($_POST[$_tabType . 'from']))
		{
			if ($_POST[$_tabType . 'from'] == '-1')
			{
				$_fromEmailAddress = $_SWIFT->Staff->GetProperty('email');
			} else if ($_POST[$_tabType . 'from'] == '0') {
				$_fromEmailAddress = $_SWIFT->Settings->Get('general_returnemail');
			} else if (isset($_emailQueueCache['list'][$_POST[$_tabType . 'from']])) {
				if (!empty($_emailQueueCache['list'][$_POST[$_tabType . 'from']]['customfromemail'])) {
					$_fromEmailAddress = $_emailQueueCache['list'][$_POST[$_tabType . 'from']]['customfromemail'];
				} else {
					$_fromEmailAddress = $_emailQueueCache['list'][$_POST[$_tabType . 'from']]['email'];
				}
			}
		}

		return $_fromEmailAddress;
	}

	/**
	 * Processes the common actions associated in Reply/Forward tabs.
	 *
	 * @author Varun Shoor
	 * @param SWIFT_Ticket $_SWIFT_TicketObject The SWIFT_Ticket Object Pointer
	 * @param string $_tabType The Tab Type
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	protected function _ProcessDispatchTab(SWIFT_Ticket $_SWIFT_TicketObject, $_tabType)
	{	$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Process the notes
		$_SWIFT_UserObject = $_SWIFT_TicketObject->GetUserObject();

		if (isset($_POST[$_tabType . 'ticketnotes']) && trim($_POST[$_tabType . 'ticketnotes']) != '') {
			/*
			 * BUG FIX - Saloni Dhall
			 *
			 * SWIFT-1278 "New Ticket Note" notification does not work, when Note is added while replying the ticket
			 *
			 * Comments: Trigger notification event
			 */
			$_SWIFT_TicketObject->NotificationManager->SetEvent('newticketnotes');

			$_staffName = $_SWIFT->Staff->GetProperty('fullname');
			$_staffEmail = $_SWIFT->Staff->GetProperty('email');

			$_SWIFT_TicketObject->SetWatcherProperties($_staffName, sprintf($_SWIFT->Language->Get('watcherprefix'), $_staffName, $_staffEmail) . SWIFT_CRLF . $_POST[$_tabType . 'ticketnotes']);
			$_SWIFT_TicketObject->CreateNote($_SWIFT_UserObject, $_POST[$_tabType . 'ticketnotes'],
					$_POST['notecolor_' . $_tabType . 'ticketnotes'], $_POST[$_tabType . 'notetype'], false);
		}

		// Process Ticket Priorities
		$_departmentField = $_tabType . 'departmentid';
		$_ownerField = $_tabType . 'ownerstaffid';
		$_ticketTypeField = $_tabType . 'tickettypeid';
		$_ticketStatusField = $_tabType . 'ticketstatusid';
		$_ticketPriorityField = $_tabType . 'ticketpriorityid';

		if (isset($_POST[$_departmentField]) && $_POST[$_departmentField] != '0' &&
				$_POST[$_departmentField] != $_SWIFT_TicketObject->GetProperty('departmentid'))
		{
			$_SWIFT_TicketObject->SetDepartment($_POST[$_departmentField]);
		}

		if (isset($_POST[$_ownerField]) && $_POST[$_ownerField] != $_SWIFT_TicketObject->GetProperty('ownerstaffid'))
		{
			$_SWIFT_TicketObject->SetOwner($_POST[$_ownerField]);
		}

		if (isset($_POST[$_ticketTypeField]) && $_POST[$_ticketTypeField] != $_SWIFT_TicketObject->GetProperty('tickettypeid'))
		{
			$_SWIFT_TicketObject->SetType($_POST[$_ticketTypeField]);
		}

		if (isset($_POST[$_ticketStatusField]) && $_POST[$_ticketStatusField] != $_SWIFT_TicketObject->GetProperty('ticketstatusid'))
		{
			$_SWIFT_TicketObject->SetStatus($_POST[$_ticketStatusField]);
		}

		if (isset($_POST[$_ticketPriorityField]) && $_POST[$_ticketPriorityField] != $_SWIFT_TicketObject->GetProperty('priorityid'))
		{
			$_SWIFT_TicketObject->SetPriority($_POST[$_ticketPriorityField]);
		}

		// Update Tags
		if ($_SWIFT->Staff->GetPermission('staff_canupdatetags') != '0') {
			SWIFT_Tag::Process(SWIFT_TagLink::TYPE_TICKET, $_SWIFT_TicketObject->GetTicketID(),
				SWIFT_UserInterface::GetMultipleInputValues($_tabType . 'tags'), $_SWIFT->Staff->GetStaffID());
		}

		// Update Recipients
		SWIFT_TicketRecipient::DeleteOnTicket(array($_SWIFT_TicketObject->GetTicketID()), true);

		$_ccEmailContainer          = self::GetSanitizedEmailList($_tabType . 'cc');
		$_bccEmailContainer         = self::GetSanitizedEmailList($_tabType . 'bcc');
		$_destinationEmailContainer = self::GetSanitizedEmailList($_tabType . 'to');
		/*
		 * BUG FIX - Mansi Wason
		 *
	     * SWIFT-1618 If we forward a ticket to more than one e-mail address, mail will be received at first address only
		 *
	     * Comments: Add multiple To: address to CC: list, except first To: email address, which would be marked as it is.
		 */
		array_shift($_destinationEmailContainer);

		$_ccEmailContainer         = !empty($_destinationEmailContainer) ? array_merge($_ccEmailContainer, $_destinationEmailContainer) : $_ccEmailContainer;
		$_thirdpartyEmailContainer = array();

		$_checkboxCCEmailContainer  = self::GetSanitizedEmailList($_tabType . 'cc', true);
		$_checkboxBCCEmailContainer = self::GetSanitizedEmailList($_tabType . 'bcc', true);

		$_ignoreCCEmailList = $_ignoreBCCEmailList = array();

		if (_is_array($_destinationEmailContainer) && count($_destinationEmailContainer) > 1) {
			foreach ($_destinationEmailContainer as $_key => $_emailAddress) {
				if ($_key == 0) {
					continue;
				}

				if (!in_array($_emailAddress, $_ccEmailContainer)) {
					if ($_tabType == 'forward' && isset($_POST['optforward_addrecipients']) && is_array($_POST['optforward_addrecipients'])
						&& in_array($_emailAddress, $_POST['optforward_addrecipients'])
					) {
						$_thirdpartyEmailContainer[] = $_emailAddress;
					} else if ($_tabType != 'forward') {
						$_ccEmailContainer[] = $_emailAddress;
					}
				}
			}
		}

		if (_is_array($_ccEmailContainer)) {
			SWIFT_TicketRecipient::Create($_SWIFT_TicketObject, SWIFT_TicketRecipient::TYPE_CC, $_ccEmailContainer);

			foreach ($_ccEmailContainer as $_emailAddress)
			{
				$_checkHash = md5('taginputcheck_' . $_tabType . 'cc' . $_emailAddress);

				// Is it an existing entry AND the user didnt check it?
				if (isset($_POST[$_checkHash]) && !in_array($_emailAddress, $_checkboxCCEmailContainer))
				{
					$_ignoreCCEmailList[] = $_emailAddress;
				}
			}

		}

		/*
		 * BUG FIX - Varun Shoor
		 *
		 * SWIFT-1100 Forwarding a ticket to more than one email adds the 2nd address or further in CC list instead of third party
		 *
		 */
		if (_is_array($_thirdpartyEmailContainer)) {
			SWIFT_TicketRecipient::Create($_SWIFT_TicketObject, SWIFT_TicketRecipient::TYPE_THIRDPARTY, $_thirdpartyEmailContainer);

			foreach ($_thirdpartyEmailContainer as $_emailAddress)
			{
				$_ccEmailContainer[] = $_emailAddress;
			}
		}


		if (_is_array($_bccEmailContainer)) {
			SWIFT_TicketRecipient::Create($_SWIFT_TicketObject, SWIFT_TicketRecipient::TYPE_BCC, $_bccEmailContainer);

			foreach ($_bccEmailContainer as $_emailAddress)
			{
				$_checkHash = md5('taginputcheck_' . $_tabType . 'bcc' . $_emailAddress);

				// Is it an existing entry AND the user didnt check it?
				if (isset($_POST[$_checkHash]) && !in_array($_emailAddress, $_checkboxBCCEmailContainer))
				{
					$_ignoreBCCEmailList[] = $_emailAddress;
				}
			}
		}

		SWIFT::Set('_ignoreCCEmail', $_ignoreCCEmailList);
		SWIFT::Set('_ignoreBCCEmail', $_ignoreBCCEmailList);

		// Process Options
		$_dueDateline = GetDateFieldTimestamp($_tabType . 'due');
		$_resolutionDueDateline = GetDateFieldTimestamp($_tabType . 'resolutiondue');

		// Due Dateline
		if (!empty($_dueDateline) && $_SWIFT_TicketObject->GetProperty('duetime') != '0' && gmdate('d M Y h:i A', $_dueDateline) != gmdate('d M Y h:i A', $_SWIFT_TicketObject->GetProperty('duetime'))) {
			$_SWIFT_TicketObject->SetDue($_dueDateline);

		// We need to clear it?
		} else if ($_tabType != 'newticket' && empty($_dueDateline) && $_SWIFT_TicketObject->GetProperty('duetime') != '0') {
			/*
			 * BUG FIX - Bishwanath Jha
			 *
			 * SWIFT-2078: SLA plan is not applied correctly when ticket status is changed with staff reply
			 *
			 * Comments: Added this method to execute on shutdown. which allow SLA calculation first then clear overdue time.
			 */
			register_shutdown_function(array($_SWIFT_TicketObject, 'ClearOverdue'));
		}

		// Resolution Due Dateline
		if (!empty($_resolutionDueDateline) && gmdate('d M Y h:i A', $_resolutionDueDateline) != gmdate('d M Y h:i A', $_SWIFT_TicketObject->GetProperty('resolutionduedateline')) && $_SWIFT_TicketObject->GetProperty('isresolved') != '1') {
			$_SWIFT_TicketObject->SetResolutionDue($_resolutionDueDateline);

		// We need to clear it?
		} else if ($_tabType != 'newticket' && empty($_resolutionDueDateline) && $_SWIFT_TicketObject->GetProperty('resolutionduedateline') != '0') {
			$_SWIFT_TicketObject->ClearResolutionDue();
		}

		// Process Draft
		if ($_SWIFT_TicketObject->GetProperty('hasdraft') == '1')
		{
			SWIFT_TicketDraft::DeleteOnTicket(array($_SWIFT_TicketObject->GetTicketID()));

			$_SWIFT_TicketObject->ClearHasDraft();
		}

		// Time tracking stuff
		if (!empty($_POST[$_tabType . 'billingtimeworked']) || !empty($_POST[$_tabType . 'billingtimebillable']))
		{
			// Create the time worked entry
			$_SWIFT_TicketTimeTrackObject = SWIFT_TicketTimeTrack::Create($_SWIFT_TicketObject, $_SWIFT->Staff,
					self::GetBillingTime($_POST[$_tabType . 'billingtimeworked']), self::GetBillingTime($_POST[$_tabType . 'billingtimebillable']),
					1, '', $_SWIFT->Staff, DATENOW, DATENOW);
		}

		return true;
	}

	/**
	 * Ticket Save as Draft
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function SaveAsDraft($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (empty($_ticketID)) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		} else if ($_SWIFT->Staff->GetPermission('staff_tcansaveasdraft') == '0') {
			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff)) {
			echo $this->Language->Get('msgnoperm');

			return false;
		}

		$_SWIFT_TicketViewObject = SWIFT_TicketViewRenderer::GetDefaultTicketViewObject($_departmentID);

		$_nextTicketID = false;
		if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_NEXTTICKET) {
			$_nextTicketID = SWIFT_TicketViewRenderer::GetNextPreviousTicketID($_SWIFT_TicketObject, 'next', $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
		}

		$this->_ProcessDispatchTab($_SWIFT_TicketObject, 'reply');

		// Save as Draft
		if (trim($_POST['replycontents']) == '')
		{
			SWIFT_TicketDraft::DeleteOnTicket(array($_SWIFT_TicketObject->GetTicketID()));
			$_SWIFT_TicketObject->ClearHasDraft();
		} else {
			SWIFT_TicketDraft::CreateIfNotExists($_SWIFT_TicketObject, $_SWIFT->Staff, $_POST['replycontents']);
		}

		if (isset($_POST['optreply_watch']) && $_POST['optreply_watch'] == '1')
		{
			SWIFT_Ticket::Watch(array($_SWIFT_TicketObject->GetTicketID()), $_SWIFT->Staff);
		} else {
			SWIFT_Ticket::UnWatch(array($_SWIFT_TicketObject->GetTicketID()), $_SWIFT->Staff);
		}

		$_SWIFT_TicketObject->ProcessUpdatePool();
		SWIFT_TicketManager::RebuildCache();

		// Does the new department belong to this staff? if not, we need to jump him back to list!
		$_assignedDepartmentIDList = $_SWIFT->Staff->GetAssignedDepartments();
		if (isset($_POST['replydepartmentid']) && !empty($_POST['replydepartmentid']) && !in_array($_POST['replydepartmentid'], $_assignedDepartmentIDList)) {
			$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);

			return true;
		}

		if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_TICKET)
		{
			$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);
		} else if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_ACTIVETICKETLIST) {
			$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);

		} else if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_TOPTICKETLIST) {
			$this->Load->Controller('Manage')->Redirect('inbox', -1, -1, -1);

		} else if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_NEXTTICKET) {
			if (!empty($_nextTicketID))
			{
				$this->Load->Method('View', $_nextTicketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);
			} else {
				$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
			}

		}

		return true;
	}

	/**
	 * New Ticket Submission Processor
	 *
	 * @author Varun Shoor
	 * @param string $_ticketType The Ticket Type
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function NewTicketSubmit($_ticketType)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if ($_ticketType != 'sendmail' && $_ticketType != 'user') {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		} else if ($_SWIFT->Staff->GetPermission('staff_tcaninsertticket') == '0') {
			return false;
		}

		/**
		 * ---------------------------------------------
		 * Begin Error Checking
		 * ---------------------------------------------
		 */
		$_POST['tickettype'] = $_ticketType;

		$_POST['departmentid'] = $_POST['newticketdepartmentid'];

		if (trim($_POST['newticketsubject']) == '' || trim($_POST['newticketcontents']) == '')
		{

			$this->UserInterface->CheckFields('newticketsubject', 'newticketcontents');

			$this->UserInterface->Error($this->Language->Get('titlefieldempty'), $this->Language->Get('msgfieldempty'));

			$this->Load->NewTicketForm();

			return false;

		// Only check TO field for the Send Mail Option
		} else if ($_ticketType == 'sendmail' && (!SWIFT_UserInterface::GetMultipleInputValues('newticketto') ||
				!_is_array(SWIFT_UserInterface::GetMultipleInputValues('newticketto')) || !$this->_CheckPOSTEmailContainer('newticketto'))) {

			SWIFT::ErrorField('newticketto');

			$this->UserInterface->Error($this->Language->Get('titlefieldempty'), $this->Language->Get('msgfieldempty'));

			$this->Load->NewTicketForm();

			return false;

		// Check sanity of all properties
		} else if (!isset($_POST['newticketdepartmentid']) || empty($_POST['newticketdepartmentid']) ||
				!isset($_POST['newticketticketstatusid']) || empty($_POST['newticketticketstatusid']) ||
				!isset($_POST['newticketownerstaffid']) ||
				!isset($_POST['newtickettickettypeid']) || empty($_POST['newtickettickettypeid']) ||
				!isset($_POST['newticketticketpriorityid']) || empty($_POST['newticketticketpriorityid'])) {
			$this->UserInterface->Error($this->Language->Get('titlefieldempty'), $this->Language->Get('msgfieldempty'));

			$this->Load->NewTicketForm();

			return false;

		// Check User ID
		} else if ($_ticketType == 'user' && (!isset($_POST['autocomplete_userid']) || empty($_POST['autocomplete_userid']))) {
			SWIFT::ErrorField('userid');

			$this->UserInterface->Error($this->Language->Get('titlefieldempty'), $this->Language->Get('msgfieldempty'));

			$this->Load->NewTicketForm();

			return false;

		}

		// Custom Field Check
		$_customFieldCheckResult = $this->CustomFieldManager->Check(SWIFT_CustomFieldManager::MODE_POST, SWIFT_UserInterface::MODE_INSERT,
				array(SWIFT_CustomFieldGroup::GROUP_STAFFTICKET, SWIFT_CustomFieldGroup::GROUP_STAFFUSERTICKET), SWIFT_CustomFieldManager::CHECKMODE_STAFF, $_POST['newticketdepartmentid']);
		if ($_customFieldCheckResult[0] == false)
		{
			call_user_func_array(array('SWIFT', 'ErrorField'), $_customFieldCheckResult[1]);

			$this->UserInterface->Error($this->Language->Get('titlefieldempty'), $this->Language->Get('msgfieldempty'));

			$this->Load->NewTicketForm();

			return false;
		}

		// Load the user object for the user based tickets
		$_SWIFT_UserObject = false;
		if ($_ticketType == 'user')
		{
			$_SWIFT_UserObject = new SWIFT_User(new SWIFT_DataID($_POST['autocomplete_userid']));
			if (!$_SWIFT_UserObject instanceof SWIFT_User || !$_SWIFT_UserObject->GetIsClassLoaded())
			{
				throw new SWIFT_Exception(SWIFT_INVALIDDATA);
			}
		}

		/**
		 * BUG FIX - Ravi Sharma <ravi.sharma@kayako.com>
		 *
		 * SWIFT-1121 - Macros do not assign ownership
		 */
		$_assignedDepartmentIDList = $_SWIFT->Staff->GetAssignedDepartments();
		if (!in_array($_POST['departmentid'], $_assignedDepartmentIDList) && $_SWIFT->Settings->Get('t_restrictnewticket') == '1') {
			$this->UserInterface->DisplayError($this->Language->Get('titlenoperm'), $this->Language->Get('msgnoperm'));

			return false;
		}

		$_emailQueueCache = $_SWIFT->Cache->Get('queuecache');
		$_templateGroupCache = $_SWIFT->Cache->Get('templategroupcache');
		$_emailQueueID = 0;
		if ($_POST['newticketfrom'] > 0 && isset($_emailQueueCache['list'][$_POST['newticketfrom']]))
		{
			$_emailQueueID = $_POST['newticketfrom'];
		}

		$_dontSendEmail = false;
		if (!isset($_POST['optnewticket_sendemail']) || (isset($_POST['optnewticket_sendmail']) && $_POST['optnewticket_sendmail'] != '1'))
		{
			$_dontSendEmail = true;
		}

		$_dispatchAutoResponder = false;
		if ($_ticketType != 'sendmail' && isset($_POST['optnewticket_sendar']) && $_POST['optnewticket_sendar'] == '1')
		{
			$_dispatchAutoResponder = true;
		}

		$_isPrivate = false;
		if (isset($_POST['optnewticket_private']) && $_POST['optnewticket_private'] == '1')
		{
			$_dontSendEmail = true;
			$_isPrivate = true;
		}

		// Create the ticket
		$_creatorFullName = $_creatorEmail = $_phoneNumber = $_destinationEmail = '';
		$_userID = 0;
		$_ticketPhoneType = SWIFT_Ticket::TYPE_DEFAULT;
		$_ticketCreator = SWIFT_Ticket::CREATOR_STAFF;
		$_destinationEmailContainer = self::GetSanitizedEmailList('newticketto');
		$_recurTicketType = SWIFT_TicketRecurrence::TICKETTYPE_ASUSER;

		$_ticketContents = $_POST['newticketcontents'];
		$_ticketDispatchContents = $_POST['newticketcontents'] . SWIFT_CRLF;

		$_ownerStaffID = 0;
		if (isset($_POST['newticketownerstaffid']) && $_POST['newticketownerstaffid'] != 0) {
			$_ownerStaffID = intval($_POST['newticketownerstaffid']);
		}

		if ($_ticketType == 'sendmail')
		{
			$_recurTicketType = SWIFT_TicketRecurrence::TICKETTYPE_SENDEMAIL;
			$_creatorFullName = $_SWIFT->Staff->GetProperty('fullname');
			$_creatorEmail = $_SWIFT->Staff->GetProperty('email');

			$_emailQueueContainer = false;
			if (isset($_emailQueueCache['list'][$_emailQueueID]))
			{
				$_emailQueueContainer = $_emailQueueCache['list'][$_emailQueueID];
			}

			$_templateGroupID = SWIFT_TemplateGroup::GetDefaultGroupID();

			if (_is_array($_emailQueueContainer) && isset($_templateGroupCache[$_emailQueueContainer['tgroupid']]))
			{
				$_templateGroupID = $_emailQueueContainer['tgroupid'];
			}

			$_templateGroupContainer = $_templateGroupCache[$_templateGroupID];
			$_destinationEmail = $_destinationEmailContainer[0];

			$_userID = SWIFT_Ticket::GetOrCreateUserID($_destinationEmail, $_destinationEmail, $_templateGroupContainer['regusergroupid']);

			$_ticketCreator = SWIFT_Ticket::CREATOR_STAFF;
			$_phoneNumber = '';

			// Retrieve the signature of the staff
			$_signatureContentsDefault = preg_replace("#(\r\n|\r|\n)#s", SWIFT_CRLF, $_SWIFT->Staff->GetProperty('signature'));;
			if (_is_array($_emailQueueContainer) && isset($_emailQueueContainer['contents'])) {
				$_signatureContentsDefault .= preg_replace("#(\r\n|\r|\n)#s", SWIFT_CRLF, $_emailQueueContainer['contents']);
			}

			// First create the ticket post
			$_ticketContents = $_ticketContents . SWIFT_CRLF . $_signatureContentsDefault;

		} else if ($_ticketType == 'user') {
			$_recurTicketType = SWIFT_TicketRecurrence::TICKETTYPE_ASUSER;
			$_creatorFullName = $_SWIFT_UserObject->GetProperty('fullname');
			$_creatorEmailList = $_SWIFT_UserObject->GetEmailList();
			$_creatorEmail = $_creatorEmailList[0];

			$_userID = $_SWIFT_UserObject->GetUserID();

			if (isset($_POST['optnewticket_isphone']) && $_POST['optnewticket_isphone'] == '1')
			{
				$_ticketPhoneType = SWIFT_Ticket::TYPE_PHONE;
			}

			$_ticketCreator = SWIFT_Ticket::CREATOR_USER;
			$_phoneNumber = $_SWIFT_UserObject->GetProperty('phone');

		}

		$_SWIFT_TicketObject = SWIFT_Ticket::Create($_POST['newticketsubject'], $_creatorFullName, $_creatorEmail,
													$_ticketContents, $_ownerStaffID, $_POST['newticketdepartmentid'], $_POST['newticketticketstatusid'],
													$_POST['newticketticketpriorityid'], $_POST['newtickettickettypeid'], $_userID, $_SWIFT->Staff->GetStaffID(),
													$_ticketPhoneType, $_ticketCreator, SWIFT_Ticket::CREATIONMODE_STAFFCP, $_phoneNumber, $_emailQueueID, false,
													$_destinationEmail, false, DATENOW, $_isPrivate);
		$_SWIFT_TicketPostObject = $_SWIFT_TicketObject->GetFirstPostObject();
		$_SWIFT_TicketObject->ProcessPostAttachments($_SWIFT_TicketPostObject, 'newticketattachments');


		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		$_signatureContentsDefault = $_signatureContentsHTML = '';
		if ($_ticketType == 'sendmail') {
			$_signatureContentsDefault = $_SWIFT_TicketObject->GetSignature(false, $_SWIFT->Staff);
			$_signatureContentsHTML = $_SWIFT_TicketObject->GetSignature(true, $_SWIFT->Staff);
		}

		$_ticketID = $_SWIFT_TicketObject->GetTicketID();

		$this->_ProcessDispatchTab($_SWIFT_TicketObject, 'newticket');

		// Begin Hook: staff_newticket_create
		unset($_hookCode);
		($_hookCode = SWIFT_Hook::Execute('staff_newticket_create')) ? eval($_hookCode) : false;
		// End Hook

		/*
		 * BUG FIX - Varun Shoor
		 *
		 * SWIFT-303 Staff Replies and Autoresponder are sending wrong template group name in the Support Center URL
		 * SWIFT-1004 Survey e-mail is always sent in English, even if other language is set as default
		 *
		 * Comments: Reset the template group of the ticket
		 */
		if ($_SWIFT_UserObject === false) {
			$_SWIFT_UserObject = new SWIFT_User(new SWIFT_DataID($_userID));
		}

		if ($_SWIFT_UserObject instanceof SWIFT_User && $_SWIFT_UserObject->GetIsClassLoaded()) {
			$_userTemplateGroupID = $_SWIFT_UserObject->GetTemplateGroupID();

			/**
			 * BUG FIX - Ravi Sharma <ravi.sharma@kayako.com>
			 *
			 * SWIFT-4268 Issue with ticket recurrence, if ticket is created using 'As a user' option.
			 *
			 * Comments: If user group is not linked with any template then set the default template.
			 */
			if (!empty($_userTemplateGroupID) && isset($_templateGroupCache[$_userTemplateGroupID])) {
				$_SWIFT_TicketObject->SetTemplateGroup($_userTemplateGroupID);
			} else {
				$_userTemplateGroupID = SWIFT_TemplateGroup::GetDefaultGroupID();
				$_SWIFT_TicketObject->SetTemplateGroup($_userTemplateGroupID);
			}
		}

		// We dispatch the autoresponder after creation so that we end up adding all the CC users etc.
		if ($_dispatchAutoResponder)
		{
			$_SWIFT_TicketObject->DispatchAutoresponder();
		}

		$_isHTML = false;

		$_fromEmailAddress = self::_GetDispatchFromEmail('newticket');

		if ($_POST['newticketcontents'] != '' && $_dontSendEmail == false)
		{
			// Carry out the email dispatch logic
			$_SWIFT_TicketEmailDispatchObject = new SWIFT_TicketEmailDispatch($_SWIFT_TicketObject);
			$_SWIFT_TicketEmailDispatchObject->DispatchStaffReply($_SWIFT->Staff, $_ticketDispatchContents, $_isHTML, $_fromEmailAddress, array($_signatureContentsDefault, $_signatureContentsHTML));
		}

		if (isset($_POST['optnewticket_watch']) && $_POST['optnewticket_watch'] == '1')
		{
			SWIFT_Ticket::Watch(array($_SWIFT_TicketObject->GetTicketID()), $_SWIFT->Staff);
		} else {
			SWIFT_Ticket::UnWatch(array($_SWIFT_TicketObject->GetTicketID()), $_SWIFT->Staff);
		}

		$_SWIFT_TicketObject->ProcessUpdatePool();
		SWIFT_TicketManager::RebuildCache();

		// Activity Log
		SWIFT_StaffActivityLog::AddToLog(sprintf($_SWIFT->Language->Get('log_newticket'), $_SWIFT_TicketObject->GetTicketDisplayID(), $_POST['newticketsubject']),
				SWIFT_StaffActivityLog::ACTION_INSERT, SWIFT_StaffActivityLog::SECTION_TICKETS, SWIFT_StaffActivityLog::INTERFACE_STAFF);

		// Do we need to add a macro
		$_addMacro = false;
		if (isset($_POST['optnewticket_addmacro']) && $_POST['optnewticket_addmacro'] == '1' && $_SWIFT_TicketPostObject instanceof SWIFT_TicketPost && $_SWIFT_TicketPostObject->GetIsClassLoaded())
		{
			$_addMacro = true;
		}

		// Do we need to add a KB article
		$_addKBArticle = false;
		if (isset($_POST['optnewticket_addkb']) && $_POST['optnewticket_addkb'] == '1' && $_SWIFT_TicketPostObject instanceof SWIFT_TicketPost && $_SWIFT_TicketPostObject->GetIsClassLoaded() && SWIFT_App::IsInstalled(APP_KNOWLEDGEBASE))
		{
			$_addKBArticle = true;
		}

		// Update Custom Field Values
		$this->CustomFieldManager->Update(SWIFT_CustomFieldManager::MODE_POST, SWIFT_UserInterface::MODE_INSERT,
				array(SWIFT_CustomFieldGroup::GROUP_STAFFTICKET, SWIFT_CustomFieldGroup::GROUP_STAFFUSERTICKET),
				SWIFT_CustomFieldManager::CHECKMODE_STAFF, $_SWIFT_TicketObject->GetTicketID(), $_POST['newticketdepartmentid']);

		/**
		 * ---------------------------------------------
		 * RECURRENCE PROCESSING
		 * ---------------------------------------------
		 */
		// Check permission & recurrence type
		if ($_SWIFT->Staff->GetPermission('staff_tcaninsertrecurrence') != '0' && isset($_POST['recurrencetype'])) {
			$_endType = SWIFT_TicketRecurrence::END_NOEND;
			if (isset($_POST['recurrence_endtype']) && $_POST['recurrence_endtype'] == SWIFT_TicketRecurrence::END_DATE && GetCalendarDateline($_POST['recurrence_enddateline']) != false) {
				$_endType = SWIFT_TicketRecurrence::END_DATE;
			} else if (isset($_POST['recurrence_endtype']) && $_POST['recurrence_endtype'] == SWIFT_TicketRecurrence::END_OCCURENCES && intval($_POST['recurrence_endcount']) > 0) {
				$_endType = SWIFT_TicketRecurrence::END_OCCURENCES;
			}

			// Daily
			if ($_POST['recurrencetype'] == SWIFT_TicketRecurrence::INTERVAL_DAILY) {
				$_intervalStep = intval($_POST['recurrence_daily_step']);
				$_dailyEveryWeekday = false;
				if ((empty($_intervalStep) || $_intervalStep < 0) && $_POST['recurrence_daily_type'] == 'default') {
					$_intervalStep = 1;
				}

				if ($_POST['recurrence_daily_type'] == 'extended') {
					$_intervalStep = 0;
					$_dailyEveryWeekday = true;
				}

				SWIFT_TicketRecurrence::CreateDaily($_SWIFT_TicketObject, $_SWIFT->Staff, $_recurTicketType, $_POST['newticketdepartmentid'], $_POST['newticketownerstaffid'], $_POST['newtickettickettypeid'], $_POST['newticketticketstatusid'], $_POST['newticketticketpriorityid'], $_intervalStep, $_dailyEveryWeekday, GetCalendarDateline($_POST['recurrence_start']), $_endType, GetCalendarDateline($_POST['recurrence_enddateline']), intval($_POST['recurrence_endcount']), $_dontSendEmail, $_dispatchAutoResponder);

				// Weekly
			} else if ($_POST['recurrencetype'] == SWIFT_TicketRecurrence::INTERVAL_WEEKLY) {
				$_intervalStep = intval($_POST['recurrence_weekly_step']);
				if ((empty($_intervalStep) || $_intervalStep < 0)) {
					$_intervalStep = 1;
				}

				$_isMonday = $_isTuesday = $_isWednesday = $_isThursday = $_isFriday = $_isSaturday = $_isSunday = false;
				if (isset($_POST['recurrence_weekly_ismonday'])) {
					$_isMonday = true;
				}

				if (isset($_POST['recurrence_weekly_istuesday'])) {
					$_isTuesday = true;
				}

				if (isset($_POST['recurrence_weekly_iswednesday'])) {
					$_isWednesday = true;
				}

				if (isset($_POST['recurrence_weekly_isthursday'])) {
					$_isThursday = true;
				}

				if (isset($_POST['recurrence_weekly_isfriday'])) {
					$_isFriday = true;
				}

				if (isset($_POST['recurrence_weekly_issaturday'])) {
					$_isSaturday = true;
				}

				if (isset($_POST['recurrence_weekly_issunday'])) {
					$_isSunday = true;
				}

				SWIFT_TicketRecurrence::CreateWeekly($_SWIFT_TicketObject, $_SWIFT->Staff, $_recurTicketType, $_POST['newticketdepartmentid'], $_POST['newticketownerstaffid'], $_POST['newtickettickettypeid'], $_POST['newticketticketstatusid'], $_POST['newticketticketpriorityid'], $_intervalStep, $_isMonday, $_isTuesday, $_isWednesday, $_isThursday, $_isFriday, $_isSaturday, $_isSunday, GetCalendarDateline($_POST['recurrence_start']), $_endType, GetCalendarDateline($_POST['recurrence_enddateline']), intval($_POST['recurrence_endcount']), $_dontSendEmail, $_dispatchAutoResponder);

				// Monthly
			} else if ($_POST['recurrencetype'] == SWIFT_TicketRecurrence::INTERVAL_MONTHLY) {
				$_recurrenceMonthlyType  = SWIFT_TicketRecurrence::MONTHLY_DEFAULT;
				$_monthlyExtendedDay     = 'monday';
				$_monthlyExtendedDayStep = 'first';
				$_intervalStep           = 1;
				$_monthlyDay             = date('d');

				if ($_POST['recurrence_monthly_type'] == 'extended') {
					$_recurrenceMonthlyType  = SWIFT_TicketRecurrence::MONTHLY_EXTENDED;
					$_monthlyExtendedDay     = $_POST['recurrence_monthly_extday'];
					$_monthlyExtendedDayStep = $_POST['recurrence_monthly_extdaystep'];

					$_intervalStep = intval($_POST['recurrence_monthly_stepext']);
				} else {
					$_intervalStep = intval($_POST['recurrence_monthly_step']);
					if (intval($_POST['recurrence_monthly_day']) != '0' && intval($_POST['recurrence_monthly_day']) > 0) {
						$_monthlyDay = intval($_POST['recurrence_monthly_day']);
					}
				}

				if ((empty($_intervalStep) || $_intervalStep < 0)) {
					$_intervalStep = 1;
				}

				SWIFT_TicketRecurrence::CreateMonthly($_SWIFT_TicketObject, $_SWIFT->Staff, $_recurTicketType, $_POST['newticketdepartmentid'], $_POST['newticketownerstaffid'], $_POST['newtickettickettypeid'], $_POST['newticketticketstatusid'], $_POST['newticketticketpriorityid'], $_intervalStep, $_recurrenceMonthlyType, $_monthlyDay, $_monthlyExtendedDay, $_monthlyExtendedDayStep, GetCalendarDateline($_POST['recurrence_start']), $_endType, GetCalendarDateline($_POST['recurrence_enddateline']), intval($_POST['recurrence_endcount']), $_dontSendEmail, $_dispatchAutoResponder);

				// Yearly
			} else if ($_POST['recurrencetype'] == SWIFT_TicketRecurrence::INTERVAL_YEARLY) {
				$_yearlyType            = SWIFT_TicketRecurrence::YEARLY_DEFAULT;
				$_yearlyMonthDay        = gmdate('d', DATENOW);
				$_yearlyMonth           = gmdate('n', DATENOW);
				$_yearlyExtendedDay     = 'first';
				$_yearlyExtendedDayStep = 'monday';
				$_yearlyExtendedMonth   = $_yearlyMonth;

				if ($_POST['recurrence_yearly_type'] == 'extended') {
					$_yearlyType            = SWIFT_TicketRecurrence::YEARLY_EXTENDED;
					$_yearlyExtendedDay     = $_POST['recurrence_yearly_extday'];
					$_yearlyExtendedDayStep = $_POST['recurrence_yearly_extdaystep'];
					$_yearlyExtendedMonth   = $_POST['recurrence_yearly_extmonth'];
				} else {
					$_yearlyMonthDay = intval($_POST['recurrence_yearly_monthday']);
					if (empty($_yearlyMonthDay) || $_yearlyMonthDay <= 0) {
						$_yearlyMonthDay = gmdate('d', DATENOW);
					}

					$_yearlyMonth = intval($_POST['recurrence_yearly_month']);
				}

				SWIFT_TicketRecurrence::CreateYearly($_SWIFT_TicketObject, $_SWIFT->Staff, $_recurTicketType, $_POST['newticketdepartmentid'], $_POST['newticketownerstaffid'], $_POST['newtickettickettypeid'], $_POST['newticketticketstatusid'], $_POST['newticketticketpriorityid'], $_yearlyType, $_yearlyMonth, $_yearlyMonthDay, $_yearlyExtendedDay, $_yearlyExtendedDayStep, $_yearlyExtendedMonth, GetCalendarDateline($_POST['recurrence_start']), $_endType, GetCalendarDateline($_POST['recurrence_enddateline']), intval($_POST['recurrence_endcount']), $_dontSendEmail, $_dispatchAutoResponder);
			}
		}

		// Does the new department belong to this staff? if not, we need to jump him back to list!
		$_assignedDepartmentIDList = $_SWIFT->Staff->GetAssignedDepartments();
		if (isset($_POST['newticketdepartmentid']) && !empty($_POST['newticketdepartmentid']) &&
				!in_array($_POST['newticketdepartmentid'], $_assignedDepartmentIDList)) {
			if ($_addMacro)
			{
				$this->Load->Controller('MacroReply')->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, 'inbox', -1, -1, -1, $_addKBArticle);
			} else if ($_addKBArticle) {
				$this->Load->Controller('Article', APP_KNOWLEDGEBASE)->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, 'inbox', -1, -1, -1);
			} else {
				$this->Load->Controller('Manage')->Redirect('inbox', -1, -1, -1);
			}

			return true;
		}

		if ($_addMacro)
		{
			$this->Load->Controller('MacroReply')->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, 'viewticket', -1, -1, -1, $_addKBArticle);
		} else if ($_addKBArticle) {
			$this->Load->Controller('Article', APP_KNOWLEDGEBASE)->InsertTicket($_SWIFT_TicketPostObject, $_ticketID, 'viewticket', -1, -1, -1);
		} else {
			$this->Load->Method('View', $_SWIFT_TicketObject->GetTicketID(), 'inbox', -1, -1, -1, 0);
		}

		return true;
	}

	/**
	 * Check validity of emails in  the input box
	 *
	 * @author Varun Shoor
	 * @param string $_fieldName The Field Name to Check On
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	protected function _CheckPOSTEmailContainer($_fieldName)
	{
		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		$_emailCount = 0;

		$_postEmailValues = SWIFT_UserInterface::GetMultipleInputValues($_fieldName);
		if (_is_array($_postEmailValues))
		{
			foreach ($_postEmailValues as $_key => $_val)
			{
				if (!IsEmailValid($_val))
				{
					return false;
				} else {
					$_emailCount++;
				}
			}
		}

		if (!$_emailCount)
		{
			return false;
		}

		return true;
	}

	/**
	 * Ticket Dispatch Window
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function Dispatch($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (empty($_ticketID)) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		} else if ($_SWIFT->Staff->GetPermission('staff_tcanupdateticket') == '0') {
			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff)) {
			echo $this->Language->Get('msgnoperm');

			return false;
		}

		SWIFT::Set('ticketurlsuffix', $_listType . '/' . $_departmentID . '/' . $_ticketStatusID . '/' . $_ticketTypeID . '/' . $_ticketLimitOffset);

		$this->UserInterface->Header($this->Language->Get('tickets') . ' > ' . $this->Language->Get('dispatch'), self::MENU_ID, self::NAVIGATION_ID);
		$this->View->RenderDispatchForm(SWIFT_UserInterface::MODE_INSERT, $_SWIFT_TicketObject);
		$this->UserInterface->Footer();

		return true;
	}

	/**
	 * Ticket Dispatch Submission
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param string $_listType (OPTIONAL) The List Type
	 * @param int $_departmentID (OPTIONAL) The Department ID
	 * @param int $_ticketStatusID (OPTIONAL) The Ticket Status ID
	 * @param int $_ticketTypeID (OPTIONAL) The Ticket Type ID
	 * @param int $_ticketLimitOffset (OPTIONAL) The offset to display ticket posts on
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function DispatchSubmit($_ticketID, $_listType = 'inbox', $_departmentID = -1, $_ticketStatusID = -1, $_ticketTypeID = -1,
			$_ticketLimitOffset = 0)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (empty($_ticketID)) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		} else if ($_SWIFT->Staff->GetPermission('staff_tcanupdateticket') == '0') {
			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff)) {
			echo $this->Language->Get('msgnoperm');

			return false;
		}

		$_SWIFT_TicketViewObject = SWIFT_TicketViewRenderer::GetDefaultTicketViewObject($_departmentID);

		$_nextTicketID = false;
		if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_NEXTTICKET) {
			$_nextTicketID = SWIFT_TicketViewRenderer::GetNextPreviousTicketID($_SWIFT_TicketObject, 'next', $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
		}

		$_staffCache = $this->Cache->Get('staffcache');

		if (!empty($_POST['dispatchstaffid']) && isset($_staffCache[$_POST['dispatchstaffid']]))
		{
			$_SWIFT_TicketObject->SetOwner($_POST['dispatchstaffid']);
		}

		/*
		 * BUG FIX - Abhishek Mittal
		 *
		 * SWIFT-3835: Incorrect SLA plan gets linked with the ticket when ticket is moved from a resolved status to unresolved status
		 *
		 * Comments: Update reply due time only in case if SLA plan changed
		 */
		$_SWIFT_TicketObject->ExecuteSLA(false, true, false);

		if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_TICKET)
		{
			$this->Load->Method('View', $_ticketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);
		} else if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_ACTIVETICKETLIST) {
			$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);

		} else if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_TOPTICKETLIST) {
			$this->Load->Controller('Manage')->Redirect('inbox', -1, -1, -1);

		} else if ($_SWIFT_TicketViewObject->GetProperty('afterreplyaction') == SWIFT_TicketView::AFTERREPLY_NEXTTICKET) {
			if (!empty($_nextTicketID))
			{
				$this->Load->Method('View', $_nextTicketID, $_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketLimitOffset);
			} else {
				$this->Load->Controller('Manage')->Redirect($_listType, $_departmentID, $_ticketStatusID, $_ticketTypeID);
			}

		}
		return true;
	}

	/**
	 * Ticket Rating Handler
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function Rating($_ticketID)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (empty($_ticketID)) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		} else if (!isset($_POST['ratingid']) || empty($_POST['ratingid']) || !isset($_POST['ratingvalue'])) {
			return false;

		} else if ($_SWIFT->Staff->GetPermission('staff_canviewratings') == '0' || $_SWIFT->Staff->GetPermission('staff_canupdateratings') == '0') {
			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff)) {
			echo $this->Language->Get('msgnoperm');

			return false;
		}

		$_SWIFT_RatingObject = new SWIFT_Rating(intval($_POST['ratingid']));
		if (!$_SWIFT_RatingObject instanceof SWIFT_Rating || !$_SWIFT_RatingObject->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		SWIFT_RatingResult::CreateOrUpdateIfExists($_SWIFT_RatingObject, $_SWIFT_TicketObject->GetTicketID(), $_POST['ratingvalue'], SWIFT_RatingResult::CREATOR_STAFF, $_SWIFT->Staff->GetStaffID());

		$_SWIFT_TicketObject->MarkHasRatings();

		return true;
	}


	/**
	 * Ticket Post Rating Handler
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param int $_ticketPostID The Ticket Post ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function RatingPost($_ticketID, $_ticketPostID)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		} else if (empty($_ticketID)) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);

			return false;
		} else if (!isset($_POST['ratingid']) || empty($_POST['ratingid']) || !isset($_POST['ratingvalue'])) {
			return false;

		} else if ($_SWIFT->Staff->GetPermission('staff_canviewratings') == '0' || $_SWIFT->Staff->GetPermission('staff_canupdateratings') == '0') {
			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff)) {
			echo $this->Language->Get('msgnoperm');

			return false;
		}

		$_SWIFT_TicketPostObject = new SWIFT_TicketPost(new SWIFT_DataID($_ticketPostID));
		if (!$_SWIFT_TicketPostObject instanceof SWIFT_TicketPost && !$_SWIFT_TicketPostObject->GetIsClassLoaded() || $_SWIFT_TicketPostObject->GetProperty('ticketid') != $_SWIFT_TicketObject->GetTicketID())
		{
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		$_SWIFT_RatingObject = new SWIFT_Rating(intval($_POST['ratingid']));
		if (!$_SWIFT_RatingObject instanceof SWIFT_Rating || !$_SWIFT_RatingObject->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		SWIFT_RatingResult::CreateOrUpdateIfExists($_SWIFT_RatingObject, $_SWIFT_TicketPostObject->GetTicketPostID(), $_POST['ratingvalue'], SWIFT_RatingResult::CREATOR_STAFF, $_SWIFT->Staff->GetStaffID());

		$_SWIFT_TicketObject->MarkHasRatings();

		return true;
	}

	/**
	 * Process the follow-up POST data and create a follow up entry
	 *
	 * @author Varun Shoor
	 * @param SWIFT_Ticket $_SWIFT_TicketObject The SWIFT_Ticket Object Pointer
	 * @param string $_prefix The Prefix for Variables (to prevent race errors)
	 * @param SWIFT_TicketFollowUp (OPTIONAL) The SWIFT_TicketFollowUp Object for Updates
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If Invalid Data is Provided
	 */
	public function _ProcessFollowUp(SWIFT_Ticket $_SWIFT_TicketObject, $_prefix, SWIFT_TicketFollowUp $_SWIFT_TicketFollowUpObject = null)
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded())
		{
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		} else if (!isset($_POST[$_prefix . 'followuptype'])) {
			return false;
		}

		$_followUpDate = false;
		if ($_POST[$_prefix . 'followuptype'] == 'custom')
		{
			$_followUpDate = GetDateFieldTimestamp($_prefix . 'followupcustomvalue');
		} else {
			$_followUpDate = self::_ReturnFollowUpDate($_POST[$_prefix . 'followuptype'], $_POST[$_prefix . 'followupvalue']);
		}

		if (empty($_followUpDate))
		{
			return false;
		}

		// Now that we have the follow up execution date, we process the properties
		$_executionDateline = $_followUpDate;

		$_doChangeProperties = false;
		$_ownerStaffID = $_departmentID = $_ticketStatusID = $_ticketTypeID = $_ticketPriorityID = 0;

		if (isset($_POST[$_prefix . 'dochangeproperties']) && $_POST[$_prefix . 'dochangeproperties'] == 1)
		{
			$_doChangeProperties = true;
			$_ownerStaffID = intval($_POST[$_prefix . 'ownerstaffid']);
			$_departmentID = intval($_POST[$_prefix . 'departmentid']);
			$_ticketStatusID = intval($_POST[$_prefix . 'ticketstatusid']);
			$_ticketTypeID = intval($_POST[$_prefix . 'tickettypeid']);
			$_ticketPriorityID = intval($_POST[$_prefix . 'ticketpriorityid']);
		}

		$_doChangeDueDateline = false;
		$_dueDateline = $_resolutionDueDateline = 0;
		$_timeWorked = $_timeBillable = 0;

		$_doNote = false;
		$_noteType = 'ticket';
		$_noteColor = 1;
		$_ticketNotes = '';
		if (isset($_POST[$_prefix . 'donote']) && $_POST[$_prefix . 'donote'] == 1)
		{
			$_doNote = true;
			$_noteType = $_POST[$_prefix . 'notetype'];
			$_noteColor = intval($_POST['notecolor_' . $_prefix . 'ticketnotes']);
			$_ticketNotes = $_POST[$_prefix . 'ticketnotes'];
		}

		$_doReply = false;
		$_replyContents = '';
		if (isset($_POST[$_prefix . 'doreply']) && $_POST[$_prefix . 'doreply'] == 1)
		{
			$_doReply = true;

			/*
			 * BUG FIX - Varun Shoor
			 *
			 * SWIFT-1508 Signatures does not append on ticket, if ticket is replied using 'Follow-Up' tab
			 *
			 * Comments: None
			 */
			$_signatureContentsDefault = preg_replace("#(\r\n|\r|\n)#s", SWIFT_CRLF, $_SWIFT->Staff->GetProperty('signature'));
			$_replyContents = $_POST[$_prefix . 'replycontents'];

			if (!empty($_signatureContentsDefault)) {
	            $_replyContents = $_POST[$_prefix . 'replycontents'] . SWIFT_CRLF . $_signatureContentsDefault;
			}
		}

		$_doForward = false;
		$_forwardEmailTo = '';
		$_forwardContents = '';
		if (isset($_POST[$_prefix . 'doforward']) && $_POST[$_prefix . 'doforward'] == '1')
		{
			$_forwardEmailToContainer = self::GetSanitizedEmailList($_prefix . 'to');

			if (_is_array($_forwardEmailToContainer))
			{
				$_doForward = true;
				$_forwardEmailTo = $_forwardEmailToContainer[0];
				$_forwardContents = $_POST[$_prefix . 'forwardcontents'];
			}
		}

		if ($_SWIFT_TicketFollowUpObject instanceof SWIFT_TicketFollowUp && $_SWIFT_TicketFollowUpObject->GetIsClassLoaded())
		{
			$_SWIFT_TicketFollowUpObject->Update($_SWIFT_TicketObject, $_executionDateline,
			$_doChangeProperties, $_ownerStaffID, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketPriorityID,
			$_doChangeDueDateline, $_dueDateline, $_resolutionDueDateline,
			$_timeWorked, $_timeBillable,
			$_doNote, $_noteType, $_noteColor, $_ticketNotes,
			$_doReply, $_replyContents,
			$_doForward, $_forwardEmailTo, $_forwardContents,
			$_SWIFT->Staff);
		} else {
			SWIFT_TicketFollowUp::Create($_SWIFT_TicketObject, $_executionDateline,
				$_doChangeProperties, $_ownerStaffID, $_departmentID, $_ticketStatusID, $_ticketTypeID, $_ticketPriorityID,
				$_doChangeDueDateline, $_dueDateline, $_resolutionDueDateline,
				$_timeWorked, $_timeBillable,
				$_doNote, $_noteType, $_noteColor, $_ticketNotes,
				$_doReply, $_replyContents,
				$_doForward, $_forwardEmailTo, $_forwardContents,
				$_SWIFT->Staff);

		}

		$_SWIFT_TicketObject->RebuildProperties();

		return true;
	}

	/**
	 * Return a UNIX Timestamp for Follow Up
	 *
	 * @author Varun Shoor
	 * @param string $_followUpType The Follow-Up Type
	 * @param string $_followUpValue The Follow-Up Value
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If Invalid Data is Provided
	 */
	static public function _ReturnFollowUpDate($_followUpType, $_followUpValue)
	{
		$_SWIFT = SWIFT::GetInstance();

		switch ($_followUpType)
		{
			case 'minutes':
				return DATENOW+(intval($_followUpValue)*60);
				break;
			case 'hours':
				return DATENOW+(intval($_followUpValue)*60*60);
				break;
			case 'days':
				return DATENOW+(intval($_followUpValue)*60*60*24);
				break;
			case 'weeks':
				return DATENOW+(intval($_followUpValue)*60*60*24*7);
				break;
			case 'months':
				return DATENOW+(intval($_followUpValue)*60*60*24*30);
				break;
			case 'custom':
				return strtotime($_followUpValue);
				break;
			default:
				return false;
				break;
		}

		return false;
	}

	/**
	 * Split a ticket
	 *
	 * @author Simaranjit Singh
	 *
	 * @param int $_ticketID
	 *
	 * @return bool
	 * @throws SWIFT_Exception If the Class is not Loaded OR If Access Denied
	 */
	public function SplitTicket($_ticketID)
	{
		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
		}

		$_SWIFT = SWIFT::GetInstance();

		// Check permission
		if ($_SWIFT->Staff->GetPermission('staff_tcansplitticket') == '0') {
			throw new SWIFT_Exception(SWIFT_NOPERMISSION);
		}

		return $this->View->RenderSplitOrDuplicate($_ticketID, SWIFT_Ticket::MODE_SPLIT);
	}

	/**
	 * Duplicate a ticket
	 *
	 * @author Simaranjit Singh
	 *
	 * @param int $_ticketID
	 *
	 * @return bool
	 * @throws SWIFT_Exception If the Class is not Loaded OR If Access Denied
	 */
	public function DuplicateTicket($_ticketID)
	{
		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
		}

		$_SWIFT = SWIFT::GetInstance();

		// Check permission
		if ($_SWIFT->Staff->GetPermission('staff_tcanduplicateticket') == '0') {
			throw new SWIFT_Exception(SWIFT_NOPERMISSION);
		}

		return $this->View->RenderSplitOrDuplicate($_ticketID, SWIFT_Ticket::MODE_DUPLICATE);
	}

	/**
	 * Split or copy ticket submit
	 *
	 * @author Simaranjit Singh
	 *
	 * @return bool
	 * @throws SWIFT_Exception If the Class is not Loaded OR If Access Denied OR If Invalid Data is Provided
	 */
	public function SplitOrDuplicateSubmit()
	{
		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
		}

		SWIFT_Ticket::LoadLanguageTable();

		$_oldTicketID     = intval($_POST['ticketid']);
		$_oldTicketPostID = intval($_POST['splitat']);
		$_operationMode   = intval($_POST['operationmode']);

		if (($_operationMode == SWIFT_TICKET::MODE_SPLIT && $_SWIFT->Staff->GetPermission('staff_tcansplitticket') == '0') || ($_operationMode == SWIFT_TICKET::MODE_DUPLICATE && $_SWIFT->Staff->GetPermission('staff_tcanduplicateticket') == '0')) {
			throw new SWIFT_Exception(SWIFT_NOPERMISSION);
		} else if ($_operationMode != SWIFT_TICKET::MODE_SPLIT && $_operationMode != SWIFT_TICKET::MODE_DUPLICATE) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		$_phrase = IIF($_operationMode == SWIFT_TICKET::MODE_SPLIT, 'split', 'duplicate');

		$_TicketOld = new SWIFT_Ticket(new SWIFT_DataID($_oldTicketID));

		if (!$_TicketOld instanceof SWIFT_Ticket || !$_TicketOld->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		$_TicketPostOld = new SWIFT_TicketPost(new SWIFT_DataID($_oldTicketPostID));

		if (!$_TicketPostOld instanceof SWIFT_TicketPost && !$_TicketPostOld->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Get the dateline for the post from which we're going to split or copy.
		$_dateline = $_TicketPostOld->Get('dateline');

		if ($_dateline > 0) {
			// Single transaction.
			$_SWIFT->Database->StartTrans();

			$_TicketNew = SWIFT_Ticket::Create($_POST['newtitle'], $_TicketOld->Get('fullname'), $_TicketOld->Get('email'), 'DeleteMe', $_TicketOld->Get('ownerstaffid'),
				$_TicketOld->Get('departmentid'), $_TicketOld->Get('ticketstatusid'), $_TicketOld->Get('priorityid'), $_TicketOld->Get('tickettypeid'),
				$_TicketOld->Get('userid'), $_SWIFT->Staff->GetStaffID(), $_TicketOld->Get('tickettype'), SWIFT_TicketAuditLog::CREATOR_STAFF,
				$_TicketOld->Get('creationmode'), '', 0, true, $_TicketOld->Get('replyto'), false);

			$_TicketNew->SetTemplateGroup($_TicketOld->Get('tgroupid'));

			$_newTicketID = $_TicketNew->GetTicketID();

			// Get rid of the ticket post that's created as part of creating the ticket.
			SWIFT_TicketPost::DeleteOnTicket(array($_newTicketID));

			// Find and add any additional recipients.
			$_ticketRecipientContainer = SWIFT_TicketRecipient::RetrieveOnTicket($_TicketOld);

			if (_is_array($_ticketRecipientContainer)) {
				foreach ($_ticketRecipientContainer as $_recipientType => $_recipientName) {
					SWIFT_TicketRecipient::Create($_TicketNew, $_recipientType, $_recipientName);
				}
			}

			// Set up a bulk copy.
			if ($_operationMode == SWIFT_TICKET::MODE_DUPLICATE) {
				$_ticketPostContainer = $_TicketOld->GetTicketPosts(false, false, 'ASC');

				// Copy the posts first.
				foreach ($_ticketPostContainer as $_ticketPostID => $_TicketPost) {

					// If this post is one that we're meant to copy...
					if ($_TicketPost->GetTicketPostID() >= $_oldTicketPostID) {
						$_creatorType = $_TicketPost->Get('creator');

						$_newTicketPostID = SWIFT_TicketPost::Create($_TicketNew, $_TicketPost->Get('fullname'), $_TicketPost->Get('email'), $_TicketPost->Get('contents'),
							$_creatorType, $_TicketPost->Get(IIF($_creatorType == SWIFT_Ticket::CREATOR_CLIENT, 'userid', 'staffid')), $_TicketPost->Get('creationmode'),
							$_TicketPost->Get('subject'), $_TicketPost->Get('emailto'), $_TicketPost->Get('ishtml'), $_TicketPost->Get('isthirdparty'),
							$_TicketPost->Get('issurveycomment'), $_TicketPost->Get('dateline'));

						if (!empty($_newTicketPostID)) {
							$_ticketAttachmentContainer = $_TicketPost->RetrieveAttachments($_TicketOld);

							$_ticketAttachmentIDList = array_keys($_ticketAttachmentContainer);

							if (_is_array($_ticketAttachmentIDList)) {
								$_TicketPostNew = new SWIFT_TicketPost(new SWIFT_DataID($_newTicketPostID));

								foreach ($_ticketAttachmentIDList as $_ticketAttachmentID) {
									$_Attachment = new SWIFT_Attachment($_ticketAttachmentID);

									if ($_Attachment instanceof SWIFT_Attachment) {
										SWIFT_Attachment::CloneOnTicket($_TicketNew, $_TicketPostNew, $_Attachment)->SetDate($_Attachment->GetProperty('dateline'));

										unset($_Attachment);
									}
								}

								unset($_TicketPostNew);
							}
						} else {
							SWIFT::Error($_SWIFT->Language->Get('ticketsplitter'), $_SWIFT->Language->Get('no_such_post'));

							$_SWIFT->Database->Rollback();

							return false;
						}
					}
				}

				// Retrieve ticket notes
				$_ticketNoteContainer = $_TicketOld->RetrieveNotes();

				foreach ($_ticketNoteContainer as $_ticketNoteID => $_ticketNote) {

					// Create a copy of the note.
					$_newTicketNoteID = SWIFT_TicketNote::Create($_TicketNew, $_ticketNote['forstaffid'], $_ticketNote['staffid'], $_ticketNote['staffname'], $_ticketNote['note'], $_ticketNote['notecolor']);

					$_TicketNote = new SWIFT_TicketNote($_newTicketNoteID);

					$_TicketNote->UpdatePool('dateline', $_ticketNote['dateline']);
					$_TicketNote->ProcessUpdatePool();
				}
			} else {
				$_TicketSplitManager = new SWIFT_TicketSplitManager();
				$_TicketSplitManager->SetFrom($_oldTicketID)->SetTo($_newTicketID)->SetStartDateline($_dateline)->Split();
			}

			$_ticketWatcherContainer = SWIFT_TicketWatcher::RetrieveOnTicket($_TicketOld);

			foreach ($_ticketWatcherContainer as $_ticketWatcherStaffID => $_ticketWatcherList) {
				$_ticketWatcherDateline = $_ticketWatcherList['dateline'];

				$_StaffAsWatcher = new SWIFT_Staff(new SWIFT_DataID($_ticketWatcherStaffID));

				if (!$_StaffAsWatcher instanceof SWIFT_Staff || !$_StaffAsWatcher->GetIsClassLoaded()) {
					throw new SWIFT_Exception(SWIFT_INVALIDDATA);
				}

				$_ticketWatcherID = SWIFT_TicketWatcher::Create($_TicketNew, $_StaffAsWatcher);

				$_TicketWatcher = new SWIFT_TicketWatcher($_ticketWatcherID);

				$_TicketWatcher->UpdatePool('dateline', $_ticketWatcherDateline);
				$_TicketWatcher->ProcessUpdatePool();
			}

			// Create something in swticketauditlogs to record this split/copy.
			$_lastTicketPostContainer = $_SWIFT->Database->QueryFetch("SELECT MAX(ticketpostid) AS ticketpostid FROM " . TABLE_PREFIX . SWIFT_TicketPost::TABLE_NAME . "
																	   WHERE ticketid = " . intval($_oldTicketID));

			if (is_array($_lastTicketPostContainer) && !empty($_lastTicketPostContainer['ticketpostid'])) {
				$_TicketPost = new SWIFT_TicketPost(new SWIFT_DataID($_lastTicketPostContainer['ticketpostid']));

				SWIFT_TicketAuditLog::Create($_TicketOld, $_TicketPost, SWIFT_TicketAuditLog::CREATOR_STAFF, $_SWIFT->Staff->GetStaffID(), $_SWIFT->Staff->GetProperty('fullname'),
					SWIFT_TicketAuditLog::ACTION_LINKTICKET, $_SWIFT->Language->Get($_phrase . '_into') . ' ' . $_TicketNew->GetTicketDisplayID(), SWIFT_TicketAuditLog::VALUE_NONE, '');
			}

			// and for the new ticket too.
			$_firstTicketPostContainer = $_SWIFT->Database->QueryFetch("SELECT MIN(ticketpostid) AS ticketpostid FROM " . TABLE_PREFIX . SWIFT_TicketPost::TABLE_NAME . "
																		WHERE ticketid = " . intval($_newTicketID));

			if (is_array($_firstTicketPostContainer) && !empty($_firstTicketPostContainer['ticketpostid'])) {
				$_TicketPost = new SWIFT_TicketPost(new SWIFT_DataID($_firstTicketPostContainer['ticketpostid']));

				SWIFT_TicketAuditLog::Create($_TicketNew, $_TicketPost, SWIFT_TicketAuditLog::CREATOR_STAFF, $_SWIFT->Staff->GetStaffID(), $_SWIFT->Staff->GetProperty('fullname'),
					SWIFT_TicketAuditLog::ACTION_LINKTICKET, $_SWIFT->Language->Get($_phrase . '_from') . ' ' . $_TicketOld->GetTicketDisplayID(), SWIFT_TicketAuditLog::VALUE_NONE, '');
			}

			// Reset all the various counts in the owning ticket objects.
			$_TicketOld->RebuildProperties();
			$_TicketNew->RebuildProperties();

			if (isset($_POST['closeold']) && $_POST['closeold'] == '1' && $_operationMode == SWIFT_TICKET::MODE_SPLIT) {
				// Close the old ticket if requested, using the first available 'resolved' status.
				$_ticketStatusCache = $_SWIFT->Cache->Get('statuscache');
				$_ticketDepartment  = $_TicketOld->GetProperty('departmentid');

				foreach ($_ticketStatusCache as $_ticketStatus) {
					if ($_ticketStatus['markasresolved']) {
						if ($_ticketStatus['departmentid'] == 0 || $_ticketStatus['departmentid'] == $_ticketDepartment) {

							// This is available to this department, and is resolved.
							$_TicketOld->SetStatus($_ticketStatus['ticketstatusid']);

							break;
						}
					}
				}
			}

			$_SWIFT->Database->CompleteTrans();
		} else {
			SWIFT::Error($_SWIFT->Language->Get('ticketsplitter'), $_SWIFT->Language->Get('no_such_post'));
		}

		return $this->Load->Controller('Manage', APP_TICKETS)->Load->Index();
	}

	/**
	 * Render the Recurrence for this Ticket
	 *
	 * @author Parminder Singh
	 *
	 * @param int $_ticketID
	 * @param int $_ticketRecurrenceID
	 *
	 * @return bool
	 */
	public function Recurrence($_ticketID, $_ticketRecurrenceID)
	{
		$_SWIFT = SWIFT::GetInstance();

		$_Ticket = new SWIFT_Ticket(new SWIFT_DataID($_ticketID));

		// Check permission
		if (!$_Ticket->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanviewrecurrence') == '0') {
			echo $this->Language->Get('msgnoperm');

			return false;
		}

		$_TicketRecurrence = new SWIFT_TicketRecurrence(new SWIFT_DataID($_ticketRecurrenceID));

		$this->View->RenderRecurrence($_Ticket, $_TicketRecurrence);

		return true;
	}

	/**
	 * Pause/Resume ticket recurrence
	 *
	 * @author Parminder Singh
	 *
	 * @param int $_ticketID
	 * @param int $_ticketRecurrenceID
	 *
	 * @return bool
	 */
	public function PauseOrResumeRecurrence($_ticketID, $_ticketRecurrenceID)
	{
		$_SWIFT = SWIFT::GetInstance();

		$_Ticket = new SWIFT_Ticket(new SWIFT_DataID($_ticketID));

		// Check permission
		if (!$_Ticket->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanupdaterecurrence') == '0') {
			echo $this->Language->Get('msgnoperm');

			return false;
		}

		$_TicketRecurrence = new SWIFT_TicketRecurrence(new SWIFT_DataID($_ticketRecurrenceID));

		if ($_TicketRecurrence->Get('nextrecurrence') == '0') { //	If it is paused then resume it
			$_TicketRecurrence->UpdatePool('nextrecurrence', intval($_TicketRecurrence->GetNextRecurrence()));
		} else { //	Otherwise pause it
			$_TicketRecurrence->UpdatePool('nextrecurrence', '0');
		}

		$this->Load->Method('View', $_ticketID);

		return true;
	}

	/**
	 * Stop the ticket recurrence
	 *
	 * @author Parminder Singh
	 *
	 * @param int $_ticketID
	 * @param int $_ticketRecurrenceID
	 *
	 * @return bool
	 */
	public function StopRecurrence($_ticketID, $_ticketRecurrenceID)
	{
		$_SWIFT = SWIFT::GetInstance();

		$_Ticket = new SWIFT_Ticket(new SWIFT_DataID($_ticketID));

		// Check permission
		if (!$_Ticket->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcandeleterecurrence') == '0') {
			echo $this->Language->Get('msgnoperm');

			return false;
		}

		$_TicketRecurrence = new SWIFT_TicketRecurrence(new SWIFT_DataID($_ticketRecurrenceID));

		$_TicketRecurrence->Delete();

		$this->Load->Method('View', $_ticketID);

		return true;
	}

	/**
	 * Delete the ticket recurrence
	 *
	 * @author Parminder Singh
	 *
	 * @param int $_ticketID
	 * @param int $_ticketRecurrenceID
	 *
	 * @return bool
	 */
	public function UpdateRecurrence($_ticketID, $_ticketRecurrenceID)
	{
		$_SWIFT = SWIFT::GetInstance();

		$_Ticket = new SWIFT_Ticket(new SWIFT_DataID($_ticketID));

		// Check permission
		if (!$_Ticket->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanupdaterecurrence') == '0') {
			echo $this->Language->Get('msgnoperm');

			return false;
		}

		$_TicketRecurrence = new SWIFT_TicketRecurrence(new SWIFT_DataID($_ticketRecurrenceID));

		if (isset($_POST['recurrencetype'])) {

			// Reset recurrence fields before updating
			$_TicketRecurrence->Reset();

			// Daily
			if ($_POST['recurrencetype'] == SWIFT_TicketRecurrence::INTERVAL_DAILY) {
				$_intervalStep      = intval($_POST['recurrence_daily_step']);
				$_dailyEveryWeekday = false;
				if ((empty($_intervalStep) || $_intervalStep < 0) && $_POST['recurrence_daily_type'] == 'default') {
					$_intervalStep = 1;
				}

				if ($_POST['recurrence_daily_type'] == 'extended') {
					$_intervalStep      = 0;
					$_dailyEveryWeekday = true;
				}

				$_TicketRecurrence->UpdateDaily($_intervalStep, $_dailyEveryWeekday);
				// Weekly
			} else if ($_POST['recurrencetype'] == SWIFT_TicketRecurrence::INTERVAL_WEEKLY) {
				$_intervalStep = intval($_POST['recurrence_weekly_step']);
				if ((empty($_intervalStep) || $_intervalStep < 0)) {
					$_intervalStep = 1;
				}

				$_isMonday = $_isTuesday = $_isWednesday = $_isThursday = $_isFriday = $_isSaturday = $_isSunday = false;
				if (isset($_POST['recurrence_weekly_ismonday'])) {
					$_isMonday = true;
				}

				if (isset($_POST['recurrence_weekly_istuesday'])) {
					$_isTuesday = true;
				}

				if (isset($_POST['recurrence_weekly_iswednesday'])) {
					$_isWednesday = true;
				}

				if (isset($_POST['recurrence_weekly_isthursday'])) {
					$_isThursday = true;
				}

				if (isset($_POST['recurrence_weekly_isfriday'])) {
					$_isFriday = true;
				}

				if (isset($_POST['recurrence_weekly_issaturday'])) {
					$_isSaturday = true;
				}

				if (isset($_POST['recurrence_weekly_issunday'])) {
					$_isSunday = true;
				}

				$_TicketRecurrence->UpdateWeekly($_intervalStep, $_isMonday, $_isTuesday, $_isWednesday, $_isThursday, $_isFriday, $_isSaturday, $_isSunday);
				// Monthly
			} else if ($_POST['recurrencetype'] == SWIFT_TicketRecurrence::INTERVAL_MONTHLY) {
				$_recurrenceMonthlyType  = SWIFT_TicketRecurrence::MONTHLY_DEFAULT;
				$_monthlyExtendedDay     = 'monday';
				$_monthlyExtendedDayStep = 'first';
				$_monthlyDay             = date('d');

				if ($_POST['recurrence_monthly_type'] == 'extended') {
					$_recurrenceMonthlyType  = SWIFT_TicketRecurrence::MONTHLY_EXTENDED;
					$_monthlyExtendedDay     = $_POST['recurrence_monthly_extday'];
					$_monthlyExtendedDayStep = $_POST['recurrence_monthly_extdaystep'];

					$_intervalStep = intval($_POST['recurrence_monthly_stepext']);
				} else {
					$_intervalStep = intval($_POST['recurrence_monthly_step']);
					if (intval($_POST['recurrence_monthly_day']) != '0' && intval($_POST['recurrence_monthly_day']) > 0) {
						$_monthlyDay = intval($_POST['recurrence_monthly_day']);
					}
				}

				if ((empty($_intervalStep) || $_intervalStep < 0)) {
					$_intervalStep = 1;
				}

				$_TicketRecurrence->UpdateMonthly($_intervalStep, $_recurrenceMonthlyType, $_monthlyDay, $_monthlyExtendedDay, $_monthlyExtendedDayStep);
				// Yearly
			} else if ($_POST['recurrencetype'] == SWIFT_TicketRecurrence::INTERVAL_YEARLY) {
				$_yearlyType            = SWIFT_TicketRecurrence::YEARLY_DEFAULT;
				$_yearlyMonthDay        = gmdate('d', DATENOW);
				$_yearlyMonth           = gmdate('n', DATENOW);
				$_yearlyExtendedDay     = 'first';
				$_yearlyExtendedDayStep = 'monday';
				$_yearlyExtendedMonth   = $_yearlyMonth;

				if ($_POST['recurrence_yearly_type'] == 'extended') {
					$_yearlyType            = SWIFT_TicketRecurrence::YEARLY_EXTENDED;
					$_yearlyExtendedDay     = $_POST['recurrence_yearly_extday'];
					$_yearlyExtendedDayStep = $_POST['recurrence_yearly_extdaystep'];
					$_yearlyExtendedMonth   = $_POST['recurrence_yearly_extmonth'];
				} else {
					$_yearlyMonthDay = intval($_POST['recurrence_yearly_monthday']);
					if (empty($_yearlyMonthDay) || $_yearlyMonthDay <= 0) {
						$_yearlyMonthDay = gmdate('d', DATENOW);
					}

					$_yearlyMonth = intval($_POST['recurrence_yearly_month']);
				}

				$_TicketRecurrence->UpdateYearly($_yearlyType, $_yearlyMonth, $_yearlyMonthDay, $_yearlyExtendedDay, $_yearlyExtendedDayStep, $_yearlyExtendedMonth);
			}

			$_endType = SWIFT_TicketRecurrence::END_NOEND;
			if ($_POST['recurrence_endtype'] == SWIFT_TicketRecurrence::END_DATE && GetCalendarDateline($_POST['recurrence_enddateline']) != false) {
				$_endType = SWIFT_TicketRecurrence::END_DATE;
			} else if (($_POST['recurrence_endtype'] == SWIFT_TicketRecurrence::END_OCCURENCES && intval($_POST['recurrence_endcount']) > 0)) {
				$_endType = SWIFT_TicketRecurrence::END_OCCURENCES;
			}

			$_TicketRecurrence->UpdateRecurrenceRange(GetCalendarDateline($_POST['recurrence_start']), $_endType, GetCalendarDateline($_POST['recurrence_enddateline']), intval($_POST['recurrence_endcount']));

			// Update next recurrence
			$_TicketRecurrence->UpdatePool('nextrecurrence', intval($_TicketRecurrence->GetNextRecurrence()));
		}

		$this->Load->Method('View', $_ticketID);

		return true;
	}

	/**
	 * Dispatch data for quoting a reply
	 *
	 * @author Varun Shoor
	 * @param int $_ticketID The Ticket ID
	 * @param int $_ticketPostID The Ticket Post ID
	 * @return bool "true" on Success, "false" otherwise
	 * @throws SWIFT_Exception If the Class is not Loaded
	 */
	public function GetQuote($_ticketID, $_ticketPostID) {

		$_SWIFT = SWIFT::GetInstance();

		if (!$this->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);

			return false;
		}

		/*
		 * BUG FIX - Parminder Singh
		 *
		 * SWIFT-2815: Uncaught Exception: Invalid data provided in ./__apps/tickets/models/Ticket/class.SWIFT_Ticket.php:409
		 *
		 * Comments: If current ticket id is merged with other tickets
		 */
		$_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);

		// Did the object load up?
		if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		// Check permission
		if (!$_SWIFT_TicketObject->CanAccess($_SWIFT->Staff) || $_SWIFT->Staff->GetPermission('staff_tcanviewtickets') == '0') {
			echo $this->Language->Get('msgnoperm');

			return false;

		}

		$_SWIFT_TicketPostObject = new SWIFT_TicketPost(new SWIFT_DataID($_ticketPostID));
		// Did the object load up?
		if (!$_SWIFT_TicketPostObject instanceof SWIFT_TicketPost || !$_SWIFT_TicketPostObject->GetIsClassLoaded()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		if ($_SWIFT_TicketPostObject->GetProperty('ticketid') != $_SWIFT_TicketObject->GetTicketID()) {
			throw new SWIFT_Exception(SWIFT_INVALIDDATA);
		}

		echo $_SWIFT_TicketPostObject->GetQuoteContents();

		return true;
	}

	/**
	 * Ability to unlink linked ticket
	 *
	 * @author Rahul Bhattacharya
	 *
	 * @param int $_ticketID
	 * @param int $_linkedTicketDisplayID
	 * @param int $_linkTypeID
	 *
	 * @return bool
	 */
	public function Unlink($_ticketID, $_linkedTicketDisplayID, $_linkTypeID)
	{
		$_SWIFT = SWIFT::GetInstance();

		$_ticketHashContainer = $_linkedTicketHashContainer = array();

		//Fetch the chainhash list of the Ticket
		$_SWIFT->Database->Query("SELECT * FROM " . TABLE_PREFIX . SWIFT_TicketLinkChain::TABLE_NAME . "
		                          WHERE ticketid = " . intval($_ticketID) . "
		                            AND ticketlinktypeid = " . intval($_linkTypeID));

		while ($_SWIFT->Database->NextRecord()) {
			$_ticketHashContainer[] = $_SWIFT->Database->Record['chainhash'];
		}

		// Fetch the chainhash list of the linked Ticket
		$_LinkedTicket = SWIFT_Ticket::GetObjectOnID($_linkedTicketDisplayID);
		$_linkedTicketID = $_LinkedTicket->GetID();

		$_SWIFT->Database->Query("SELECT * FROM " . TABLE_PREFIX . SWIFT_TicketLinkChain::TABLE_NAME . "
								  WHERE ticketid = " . intval($_linkedTicketID) . "
								    AND ticketlinktypeid = " . intval($_linkTypeID));

		while ($_SWIFT->Database->NextRecord()) {
			$_linkedTicketHashContainer[] = $_SWIFT->Database->Record['chainhash'];
		}

		$_chainHashContainer = array_intersect($_ticketHashContainer, $_linkedTicketHashContainer);

		if (_is_array($_chainHashContainer)) {
			$_finalTicketIDList = array($_linkedTicketID);
			$_chainHash         = end($_chainHashContainer);

			$_hashCount = $_SWIFT->Database->QueryFetch("SELECT COUNT(*) AS totalrecords FROM " . TABLE_PREFIX . SWIFT_TicketLinkChain::TABLE_NAME . "
														 WHERE chainhash = '" . $_SWIFT->Database->Escape($_chainHash) . "'");

			if ($_hashCount['totalrecords'] <= 2) {
				$_finalTicketIDList[] = $_ticketID;
			}

			$_finalTicketLinkChainIDList = array();
			$_SWIFT->Database->Query("SELECT * FROM " . TABLE_PREFIX . SWIFT_TicketLinkChain::TABLE_NAME . "
									  WHERE ticketid IN (" . BuildIN($_finalTicketIDList, true) . ")
										AND ticketlinktypeid = " . intval($_linkTypeID) . "
										AND chainhash = '" . $_SWIFT->Database->Escape($_chainHash) . "'");

			while ($_SWIFT->Database->NextRecord()) {
				$_finalTicketLinkChainIDList[] = $_SWIFT->Database->Record['ticketlinkchainid'];
			}

			if (_is_array($_finalTicketLinkChainIDList)) {
				SWIFT_TicketLinkChain::DeleteList($_finalTicketLinkChainIDList);
			}

			$_Ticket       = SWIFT_Ticket::GetObjectOnID($_ticketID);
			$_LinkedTicket = SWIFT_Ticket::GetObjectOnID($_linkedTicketID);

			if ($_Ticket instanceof SWIFT_Ticket && !_is_array($_Ticket->GetLinks())) {
				$_Ticket->MarkAsUnlinked();
			}

			if ($_LinkedTicket instanceof SWIFT_Ticket && !_is_array($_LinkedTicket->GetLinks())) {
				$_LinkedTicket->MarkAsUnlinked();
			}
		}

		$this->View($_ticketID, 'inbox', '-1', '-1', '-1');

		return true;
	}
}
