<?php

class Brivium_Credits_Model_Action extends XenForo_Model
{
	/**
	 * Get all actions , in their relative display order.
	 *
	 * @return array Format: [] => action info
	 */
	public function getAllActions()
	{
		if (($actions = $this->_getLocalCacheData('allActions')) === false)
		{
			$actions = $this->fetchAllKeyed('
				SELECT *
				FROM xf_credits_action
				ORDER BY display_order ASC
			', 'action_id');

			$this->setLocalCacheData('allActions', $actions);
		}

		return $actions;
	}
	
	/**
	 * Returns action's amount based on action_id.
	 *
	 * @param string $actionId
	 *
	 * @return array|false
	 */
	public function getActionAmountById($actionId = 0)
	{
		return $this->_getDb()->fetchRow('
			SELECT amount
			FROM xf_credits_action
			WHERE  action_id = ?
		', array( $actionId));
	}
	/**
	 * Fetches actions based on their actionIds.
	 * Note that if a version of the requested action does not exist
	 * in the specified style, nothing will be returned for it.
	 *
	 * @param array $actionIds List of actionIds
	 *
	 * @return array Format: [action_id] => info
	 */
	public function getActionsByIds(array $actionIds)
	{
		if (!$actionIds)
		{
			return array();
		}

		return $this->fetchAllKeyed('
			SELECT *
			FROM xf_credits_action
			WHERE action_id IN (' . $this->_getDb()->quote($actionIds) . ')
		', 'action_id');
	}
	/**
	 * Returns action records based on action_id.
	 *
	 * @param string $actionId
	 *
	 * @return array|false
	 */
	public function getActionById($actionId = 0)
	{
		return $this->_getDb()->fetchRow('
			SELECT *
			FROM xf_credits_action
			WHERE  action_id = ?
		', array( $actionId));
	}
	
	/**
	 * Returns all the actions that belong to the specified add-on.
	 *
	 * @param string $addOnId
	 *
	 * @return array Format: [title] => info
	 */
	public function getActionsInAddOn($addOnId)
	{
		return $this->fetchAllKeyed('
			SELECT *
			FROM xf_credits_action
			WHERE addon_id = ?
			ORDER BY display_order ASC
		', 'action_id', $addOnId);
	}

	
	/**
	 * Prepares an ungrouped list of actions for display.
	 *
	 * @param array $actions Format: [] => action info
	 *
	 * @return array
	 */
	public function prepareActions($actions = array())
	{
		if(empty($actions))return array();
		foreach ($actions AS &$action)
		{
			$action = $this->prepareAction($action);
		}
		return $actions;
	}

	/**
	 * Prepares a action for display.
	 *
	 * @param array $action
	 *
	 * @return array
	 */
	public function prepareAction($action = array())
	{
		if(empty($action))return array();
		$action['title'] = new XenForo_Phrase($this->getActionTitlePhraseName($action['action_id']));
		$action['revertedTitle'] = new XenForo_Phrase($this->getActionRevertedTitlePhraseName($action['action_id']));
		$action['explain'] = new XenForo_Phrase($this->getActionExplainPhraseName($action['action_id']));
		return $action;
	}
	
	public function getActionDataArray($action = array()){
		$data1 = @unserialize($action['forums']);
		if ($action['forums'] && $data1 !== false)
		{
			$action['forums'] = unserialize($action['forums']);
		}else{
			$action['forums'] = array();
		}
		$data2 = @unserialize($action['user_groups']);
		if ($action['user_groups'] && $data2 !== false)
		{
			$action['user_groups'] = unserialize($action['user_groups']);
		}else{
			$action['user_groups'] = array();
		}
		return $action;
	}
	
	/**
	 * Gets all actions in the format expected by the action cache.
	 *
	 * @return array Format: [action id] => info, with phrase cache as array
	 */
	public function getAllActionsForCache()
	{
		$this->resetLocalCacheData('allActions');

		$actions = $this->getAllActions();
		return $actions;
	}

	/**
	 * Rebuilds the full Action cache.
	 *
	 * @return array Format: [action id] => info, with phrase cache as array
	 */
	public function rebuildActionCache()
	{
		$this->resetLocalCacheData('allActions');

		$actions = $this->getAllActionsForCache();
		$currencies = $this->_getCurrencyModel()->getAllCurrencies();
		foreach($actions AS $action){
			foreach($currencies AS $currency){
				$this->_getCreditStastModel()->validCreditStastsRow($action['action_id'], $currency['currency_id']);
			}
		}
		$this->_getDataRegistryModel()->set('brcActions', $actions);

		return $actions;
	}
	
	/**
	 * Rebuilds all action caches.
	 */
	public function rebuildActionCaches()
	{
		$this->rebuildActionCache();
	}
	
	
	/**
	 * Gets the alert template name for a action.
	 *
	 * @param string $actionId
	 *
	 * @return string
	 */
	public function getActionAlertTemplateName($actionId)
	{
		return 'BRC_alert_credit_'. $actionId;
	}
	/**
	 * Gets the reverted phrase name for a action.
	 *
	 * @param string $actionId
	 *
	 * @return string
	 */
	public function getActionRevertedTitlePhraseName($actionId)
	{
		return 'BRC_action_'. $actionId.'_reverted';
	}
	/**
	 * Gets the phrase name for a action.
	 *
	 * @param string $actionId
	 *
	 * @return string
	 */
	public function getActionTitlePhraseName($actionId)
	{
		return 'BRC_action_'. $actionId;
	}
	/**
	 * Gets the action's explain phrase name.
	 *
	 * @param string $actionId
	 *
	 * @return string
	 */
	public function getActionExplainPhraseName($actionId)
	{
		return 'BRC_action_' . $actionId . '_explain';
	}
	/**
	 * Gets a action's master reverted title phrase text.
	 *
	 * @param string $actionId
	 *
	 * @return string
	 */
	public function getActionRevertedTitlePhraseValue($actionId)
	{
		$phraseName = $this->getActionRevertedTitlePhraseName( $actionId);
		return $this->_getPhraseModel()->getMasterPhraseValue($phraseName);
	}
	/**
	 * Gets a action's master title phrase text.
	 *
	 * @param string $actionId
	 *
	 * @return string
	 */
	public function getActionTitlePhraseValue($actionId)
	{
		$phraseName = $this->getActionTitlePhraseName( $actionId);
		return $this->_getPhraseModel()->getMasterPhraseValue($phraseName);
	}
	/**
	 * Gets a option's master explain phrase text.
	 *
	 * @param string $actionId
	 *
	 * @return string
	 */
	public function getActionMasterExplainPhraseValue($actionId)
	{
		$phraseName = $this->getActionExplainPhraseName($actionId);
		return $this->_getPhraseModel()->getMasterPhraseValue($phraseName);
	}
	
	/**
	 * Deletes the Actions that belong to the specified add-on.
	 *
	 * @param string $addOnId
	 */
	public function deleteActionsForAddOn($addOnId)
	{
		$db = $this->_getDb();
		$db->delete('xf_credits_action', 'addon_id = ' . $db->quote($addOnId));
	}
	/**
	 * Imports the add-on credits actions XML.
	 *
	 * @param SimpleXMLElement $xml XML element pointing to the root of the data
	 * @param string $addOnId Add-on to import for
	 * @param integer $offset Number of elements to skip
	 *
	 */
	public function importActionsAddOnXml(SimpleXMLElement $xml, $addOnId)
	{
		if($addOnId=='Brivium_Credits'){
			return;
		}
		$db = $this->_getDb();

		XenForo_Db::beginTransaction($db);
		
		$actions = XenForo_Helper_DevelopmentXml::fixPhpBug50670($xml->action);
		
		
		if(!empty($actions))$this->deleteActionsForAddOn($addOnId);
		$actionIds = array();
		foreach ($actions AS $action)
		{
			$actionIds[] = (string)$action['action_id'];
		}

		$existingActions = $this->getActionsByIds($actionIds);
		
		foreach ($actions AS $action)
		{
			$actionId = (string)$action['action_id'];

			$dw = XenForo_DataWriter::create('Brivium_Credits_DataWriter_Action');
			if (isset($existingActions[$actionId]))
			{
				$dw->setExistingData($existingActions[$actionId], true);
			}
			$dw->bulkSet(array(
				'action_id' 		=> $actionId,
				'display_order' 	=> (int)$action['display_order'],
				'revert' 			=> (int)isset($action['revert'])?$action['revert']:0,
				'multiple_event'	=> (int)isset($action['multiple_event'])?$action['multiple_event']:0,
				'allow_negative'	=> (int)isset($action['allow_negative'])?$action['allow_negative']:0,
				'negative_handle'	=> (string)isset($action['negative_handle'])?$action['negative_handle']:'',
				'addon_id' 			=> (string)$addOnId,
				'template' 			=> (string)$action->template,
			));
			
			$phrase = array(
				'title' => XenForo_Helper_DevelopmentXml::processSimpleXmlCdata((string)$action->title),
				'reverted_title' => XenForo_Helper_DevelopmentXml::processSimpleXmlCdata((string)$action->reverted_title),
				'explain' => XenForo_Helper_DevelopmentXml::processSimpleXmlCdata((string)$action->explain),
			);
			
			$dw->setExtraData(Brivium_Credits_DataWriter_Action::DATA_TITLE, $phrase['title']);
			$dw->setExtraData(Brivium_Credits_DataWriter_Action::DATA_REVERTED_TITLE, $phrase['reverted_title']);
			$dw->setExtraData(Brivium_Credits_DataWriter_Action::DATA_EXPLAIN, $phrase['explain']);
			$dw->updateContent();
			
			$dw->save();
			
		}

		XenForo_Db::commit($db);

	}
	
	/**
	 * Imports the add-on credits actions XML.
	 *
	 * @param SimpleXMLElement $xml XML element pointing to the root of the data
	 * @param string $addOnId Add-on to import for
	 * @param integer $offset Number of elements to skip
	 *
	 */
	public function importActionsXml(SimpleXMLElement $xml)
	{
		$db = $this->_getDb();

		XenForo_Db::beginTransaction($db);
		$addOnId = (string)$xml['addon_id'];
		if($addOnId){
			$this->deleteActionsForAddOn($addOnId);
		}
		
		$actions = XenForo_Helper_DevelopmentXml::fixPhpBug50670($xml->action);
		$actionIds = array();
		foreach ($actions AS $action)
		{
			$actionIds[] = (string)$action['action_id'];
		}

		$existingActions = $this->getActionsByIds($actionIds);
		foreach ($actions AS $action)
		{
			$actionId = (string)$action['action_id'];

			$dw = XenForo_DataWriter::create('Brivium_Credits_DataWriter_Action');
			if (isset($existingActions[$actionId]))
			{
				$dw->setExistingData($existingActions[$actionId], true);
			}
			$dw->bulkSet(array(
				'action_id' 		=> $actionId,
				'display_order' 	=> (int)$action['display_order'],
				'revert' 			=> (int)isset($action['revert'])?$action['revert']:0,
				'multiple_event'	=> (int)isset($action['multiple_event'])?$action['multiple_event']:0,
				'allow_negative'	=> (int)isset($action['allow_negative'])?$action['allow_negative']:0,
				'negative_handle'	=> (string)isset($action['negative_handle'])?$action['negative_handle']:'',
				'addon_id' 			=> ($addOnId === null ? (string)$action->addon_id : $addOnId),
				'template' 			=> (string)$action->template,
			));
			
			$phrase = array(
				'title' => XenForo_Helper_DevelopmentXml::processSimpleXmlCdata($action->title),
				'reverted_title' => XenForo_Helper_DevelopmentXml::processSimpleXmlCdata($action->reverted_title),
				'explain' => XenForo_Helper_DevelopmentXml::processSimpleXmlCdata($action->explain),
			);
			
			$dw->setExtraData(Brivium_Credits_DataWriter_Action::DATA_TITLE, $phrase['title']);
			$dw->setExtraData(Brivium_Credits_DataWriter_Action::DATA_REVERTED_TITLE, $phrase['reverted_title']);
			$dw->setExtraData(Brivium_Credits_DataWriter_Action::DATA_EXPLAIN, $phrase['explain']);
			$dw->updateContent();
			
			$dw->save();
			
		}

		XenForo_Db::commit($db);

	}
	
	/**
	 * Gets the DOM document that represents the action development file.
	 * @param string|null $limitAddOnId If specified, only exports actions from the specified add-on
	 * This must be turned into XML (or HTML) by the caller.
	 *
	 * @return DOMDocument
	 */
	public function getActionXml($limitAddOnId = null)
	{
		$document = new DOMDocument('1.0', 'utf-8');
		$document->formatOutput = true;
		$rootNode = $document->createElement('brc_actions');
		$document->appendChild($rootNode);
		if ($limitAddOnId !== null)
		{
			$rootNode->setAttribute('addon_id', $limitAddOnId);
			$this->appendActionsAddOnXml($rootNode, $limitAddOnId);
		}else{
			$actions = $this->getAllActions();
			$this->appendActionsXml($rootNode, $actions);
		}
		return $document;
	}
	
	
	/**
	 * Appends the add-on credits actions XML to a given DOM element.
	 *
	 * @param DOMElement $rootNode Node to append all elements to
	 * @param string $addOnId Add-on ID to be exported
	 */
	public function appendActionsAddOnXml(DOMElement $rootNode, $addOnId)
	{
		$actions = $this->getActionsInAddOn($addOnId);
		$this->appendActionsXml($rootNode,$actions);
	}
	
	public function appendActionsXml(DOMElement $rootNode,array $actions)
	{
		
		$document = $rootNode->ownerDocument;
		$actions = $this->prepareActions($actions);
		foreach ($actions AS $action)
		{
			$actionNode = $document->createElement('action');
			$actionNode->setAttribute('action_id', $action['action_id']);
			$actionNode->setAttribute('display_order', $action['display_order']);
			$actionNode->setAttribute('revert', isset($action['revert'])?$action['revert']:0);
			$actionNode->setAttribute('multiple_event', isset($action['multiple_event'])?$action['multiple_event']:0);
			$actionNode->setAttribute('allow_negative', isset($action['allow_negative'])?$action['allow_negative']:0);
			$actionNode->setAttribute('negative_handle', isset($action['negative_handle'])?$action['negative_handle']:'');
			
			XenForo_Helper_DevelopmentXml::createDomElements($actionNode, array(
				'addon_id' => $action['addon_id'],
				'template' => $action['template'],
			));
			
			$titleNode = $document->createElement('title');
			$titleNode->appendChild(XenForo_Helper_DevelopmentXml::createDomCdataSection($document, $action['title']));
			$actionNode->appendChild($titleNode);
			
			$revertedTitleNode = $document->createElement('reverted_title');
			$revertedTitleNode->appendChild(XenForo_Helper_DevelopmentXml::createDomCdataSection($document, $action['revertedTitle']));
			$actionNode->appendChild($revertedTitleNode);
			
			$explainNode = $document->createElement('explain');
			$explainNode->appendChild(XenForo_Helper_DevelopmentXml::createDomCdataSection($document, $action['explain']));
			$actionNode->appendChild($explainNode);
			
			$rootNode->appendChild($actionNode);
		}
	}
	
	protected function _getCreditStastModel()
	{
		return $this->getModelFromCache('Brivium_Credits_Model_CreditStast');
	}
	protected function _getCurrencyModel()
	{
		return $this->getModelFromCache('Brivium_Credits_Model_Currency');
	}
	/**
	 * Gets the phrase model object.
	 *
	 * @return XenForo_Model_Phrase
	 */
	protected function _getPhraseModel()
	{
		return $this->getModelFromCache('XenForo_Model_Phrase');
	}
}