<?php

class AVForums_Competitions_DataWriter_Entry extends XenForo_DataWriter
{
	/**
	 * Gets the fields that are defined for the table. See parent for explanation.
	 *
	 * @return array
	 */
	protected function _getFields()
	{
		return array(
			'xf_avforums_competitions_entry' => array(
				'entry_id'				=> array('type' => self::TYPE_UINT, 'autoIncrement' => true),
				'competition_id'		=> array('type' => self::TYPE_UINT, 'required' => true),
				'entry_date'			=> array('type' => self::TYPE_UINT, 'required' => true, 'default' => XenForo_Application::$time,
					'verification' => array('$this', '_validateEntryDate')
				),
				'user_id'				=> array('type' => self::TYPE_UINT, 'required' => true),
				'username'				=> array('type' => self::TYPE_STRING, 'maxLength' => 50, 'required' => true),
				'entry_state'			=> array('type' => self::TYPE_STRING, 'default' => 'loser',
					'allowedValues' => array('loser', 'winner', 'runner_up')
				),
				'answer_state'			=> array('type' => self::TYPE_STRING, 'default' => 'incorrect',
					'allowedValues' => array('incorrect', 'correct')
				),
				'answer_state_original'			=> array('type' => self::TYPE_STRING, 'default' => 'incorrect',
					'allowedValues' => array('incorrect', 'correct')
				),
				'given_answer'			=> array('type' => self::TYPE_STRING, 'required' => true),
				'opt_in'				=> array('type' => self::TYPE_UINT, 'default' => 0)
			)
		);
	}

	/**
	 * Gets the actual existing data out of data that was passed in. See parent for explanation.
	 *
	 * @param mixed
	 *
	 * @return array|bool
	 */
	protected function _getExistingData($data)
	{
		if (!$id = $this->_getExistingPrimaryKey($data, 'entry_id'))
		{
			return false;
		}

		return array('xf_avforums_competitions_entry' => $this->_getEntryModel()->getEntryById($id));
	}

	/**
	 * Gets SQL condition to update the existing record.
	 *
	 * @return string
	 */
	protected function _getUpdateCondition($tableName)
	{
		return 'entry_id = ' . $this->_db->quote($this->getExisting('entry_id'));
	}

	protected function _preSave()
	{
	    if($this->isInsert())
	    {
    		$conditions = array(
    			'competition_id' => $this->get('competition_id'),
    			'user_id' => $this->get('user_id')
    		);
    
    		$entry = $this->_getEntryModel()->getEntries($conditions);
    		if ($entry)
    		{
    			$this->error(new XenForo_Phrase('avforums_competitions_you_have_already_entered_this_competition'));
    		}
	    }
	}

	protected function _postSave()
	{
		if ($this->isInsert())
		{
			$entry = $this->getMergedData();

			$userWriter = XenForo_DataWriter::create('XenForo_DataWriter_User');
			$userWriter->setExistingData($entry['user_id']);

			$entryCache = $userWriter->get('competition_entries');
			$entryCache = @unserialize($entryCache);

			$entryCache[$entry['competition_id']] = $entry;

			$userWriter->set('competition_entries', @serialize($entryCache));
			$userWriter->save();

			$competitionWriter = XenForo_DataWriter::create('AVForums_Competitions_DataWriter_Competition');
			$competitionWriter->setExistingData($entry['competition_id']);

			$competitionData = array(
				'competition_entry_count' => $competitionWriter->get('competition_entry_count') + 1,
				'competition_correct_count' => $entry['answer_state'] == 'correct'
					? $competitionWriter->get('competition_correct_count') + 1
					: $competitionWriter->get('competition_correct_count'),
				'competition_optin_count' => $competitionWriter->get('competition_optin_count') + $this->get('opt_in')
			);

			$competitionWriter->bulkSet($competitionData);
			$competitionWriter->save();
		}
		
		elseif ($this->isUpdate())
		{
			$entry = $this->getMergedData();

			$userWriter = XenForo_DataWriter::create('XenForo_DataWriter_User');
			$userWriter->setExistingData($entry['user_id']);

			$entryCache = $userWriter->get('competition_entries');
			$entryCache = @unserialize($entryCache);
			
			$entryCache = array_replace($entryCache, array($entry['competition_id'] => $entry));

			$userWriter->set('competition_entries', @serialize($entryCache));
			$userWriter->save();

			$competitionWriter = XenForo_DataWriter::create('AVForums_Competitions_DataWriter_Competition');
			$competitionWriter->setExistingData($entry['competition_id']);

			$newCorrectCount = $competitionWriter->get('competition_correct_count') > 0
			? $competitionWriter->get('competition_correct_count') - 1
			: 0;

			$competitionData = array(
				'competition_correct_count' => $entry['answer_state'] == 'correct'
					? $competitionWriter->get('competition_correct_count') + 1
					: $newCorrectCount
			);

			$competitionWriter->bulkSet($competitionData);
			$competitionWriter->save();
		}
	}

	protected function _postDelete()
	{
		$userId = $this->get('user_id');
		$competitionId = $this->get('competition_id');

		$userWriter = XenForo_DataWriter::create('XenForo_DataWriter_User');
		
		if ($userWriter->setExistingData($userId)) {
		    
		    $entryCache = $userWriter->get('competition_entries');
		    $entryCache = @unserialize($entryCache);
		    
		    unset($entryCache[$competitionId]);
		    
		    $userWriter->set('competition_entries', @serialize($entryCache));
		    $userWriter->save();
		}

		$competitionWriter = XenForo_DataWriter::create('AVForums_Competitions_DataWriter_Competition');
		
		if ($competitionWriter->setExistingData($competitionId)) {

			$newCompetionCount = $competitionWriter->get('competition_entry_count') > 0 
			     ? $competitionWriter->get('competition_entry_count') - 1 
			     : 0;
			$newCorrectCount = $competitionWriter->get('competition_correct_count') > 0 
			     ? $competitionWriter->get('competition_correct_count') - 1 
			     : 0;
			$newOptCount = $competitionWriter->get('competition_optin_count') >= $this->get('opt_in') 
			     ? $competitionWriter->get('competition_optin_count') - $this->get('opt_in') 
			     : 0;
			
			$competitionData = array(
				'competition_entry_count' => $newCompetionCount,
				'competition_correct_count' => $this->get('answer_state') == 'correct'
					? $newCorrectCount
					: $competitionWriter->get('competition_correct_count'),
				'competition_optin_count' => $newOptCount
			);

			$competitionWriter->bulkSet($competitionData);
			$competitionWriter->save();
		}
	}

	protected function _validateEntryDate(&$date)
	{
		$competition = $this->_getCompetitionModel()->getCompetitionById($this->get('competition_id'));

		if ($date < $competition['competition_start'])
		{
			$this->error(new XenForo_Phrase('avforums_competitions_this_competitiontype_is_not_yet_accepting_entries'));
			return false;
		}

		if ($date > $competition['competition_end'])
		{
			$this->error(new XenForo_Phrase('avforums_competitions_this_competitiontype_is_now_closed'));
			return false;
		}

		return true;
	}

	/**
	 * @return AVForums_Competitions_Model_Competition
	 */
	protected function _getCompetitionModel()
	{
		return $this->getModelFromCache('AVForums_Competitions_Model_Competition');
	}

	/**
	 * @return AVForums_Competitions_Model_Entry
	 */
	protected function _getEntryModel()
	{
		return $this->getModelFromCache('AVForums_Competitions_Model_Entry');
	}
}