<?php

class AVForums_Competitions_DataWriter_Competition extends XenForo_DataWriter
{
	/**
	 * Following constants hold the temporary hash used to pull attachments and associate them with this message.
	 *
	 * @var string
	 */
	const DATA_ALL_HASHES = 'allHashes';

	/**
	 * Gets the fields that are defined for the table. See parent for explanation.
	 *
	 * @return array
	 */
	protected function _getFields()
	{   
		return array(
			'xf_avforums_competitions' => array(
				'competition_id'				=> array('type' => self::TYPE_UINT, 'autoIncrement' => true),
				'competition_title'				=> array('type' => self::TYPE_STRING, 'required' => true,
					'requiredError' => 'please_enter_valid_title', 'maxLength' => 255
				),
				'user_id'						=> array('type' => self::TYPE_UINT,    'required' => true),
				'username'						=> array('type' => self::TYPE_STRING, 'maxLength' => 50, 'required' => true),
				'competition_date'				=> array('type' => self::TYPE_UINT, 'required' => true, 'default' => XenForo_Application::$time),
				'competition_state'				=> array('type' => self::TYPE_STRING,  'default' => 'open',
					'allowedValues' => array('open', 'closed', 'completed')
				),
				'competition_published'			=> array('type' => self::TYPE_BOOLEAN, 'default' => 0),
				'competition_type'				=> array('type' => self::TYPE_STRING,  'default' => 'competition',
					'allowedValues' => array('competition', 'prize_draw')
				),
				'competition_prize'				=> array('type' => self::TYPE_STRING, 'maxLength' => 255, 'required' => true),
				'prize_value'					=> array('type' => self::TYPE_FLOAT, 'default' => 0),
				'competition_text'				=> array('type' => self::TYPE_STRING, 'required' => true),
				'competition_start'				=> array('type' => self::TYPE_UINT, 'required' => true,
					'verification' => array('$this', '_validateStartDate')
				),
				'competition_end'				=> array('type' => self::TYPE_UINT, 'required' => true,
					'verification' => array('$this', '_validateEndDate')
				),
				'external_link'					=> array('type' => self::TYPE_STRING, 'default' => '',
					'verification' => array('XenForo_DataWriter_Helper_Uri', 'verifyUriOrEmpty')
				),
				'competition_question'			=> array('type' => self::TYPE_STRING, 'default' => ''),
				'question_hint'					=> array('type' => self::TYPE_STRING, 'default' => ''),
				'competition_answers'			=> array('type' => self::TYPE_SERIALIZED, 'default' => serialize(array())),
				'restrictions'					=> array('type' => self::TYPE_STRING, 'default' => ''),
				'territories'					=> array('type' => self::TYPE_SERIALIZED, 'default' => serialize(array())),
				'view_user_groups'				=> array('type' => self::TYPE_SERIALIZED, 'default' => serialize(array())),
				'enter_user_groups'				=> array('type' => self::TYPE_SERIALIZED, 'default' => serialize(array())),
				'number_of_winners'				=> array('type' => self::TYPE_UINT,    'default' => 0),
				'number_of_runners_up'			=> array('type' => self::TYPE_UINT,    'default' => 0),
				'submit_text'					=> array('type' => self::TYPE_STRING, 'default' => ''),
				'sponsor'						=> array('type' => self::TYPE_STRING, 'maxLength' => 100, 'default' => ''),
				'minimum_age'					=> array('type' => self::TYPE_UINT,    'default' => 0),
				'marketing_message'				=> array('type' => self::TYPE_STRING, 'default' => ''),
				'force_thumbnail'				=> array('type' => self::TYPE_BOOLEAN, 'default' => 0),
				'competition_opt_out'			=> array('type' => self::TYPE_BOOLEAN, 'default' => 0),
				'competition_images_left'		=> array('type' => self::TYPE_BOOLEAN, 'default' => 0),
				'competition_hide_form'			=> array('type' => self::TYPE_BOOLEAN, 'default' => 0),
				'competition_node_id'			=> array('type' => self::TYPE_UINT,    'default' => 0),
				'competition_thread_id'			=> array('type' => self::TYPE_UINT,    'default' => 0),
				'competition_thread_user_id'	=> array('type' => self::TYPE_UINT,    'default' => 0),
				'competition_thread_username'	=> array('type' => self::TYPE_STRING, 'default' => ''),
				'competition_view_count'		=> array('type' => self::TYPE_UINT,    'default' => 0),
				'competition_entry_count'		=> array('type' => self::TYPE_UINT,    'default' => 0),
				'competition_correct_count'		=> array('type' => self::TYPE_UINT,    'default' => 0),
				'competition_optin_count'		=> array('type' => self::TYPE_UINT,    'default' => 0),
				'thumb_attachment_id'			=> array('type' => self::TYPE_UINT,    'default' => 0),
				'thumb_crop_area'				=> array('type' => self::TYPE_SERIALIZED, 'default' => serialize(array())),
				'thumb_caption'					=> array('type' => self::TYPE_STRING, 'default' => ''),
				'thumb_url'						=> array('type' => self::TYPE_STRING, 'default' => '',
					'verification' => array('XenForo_DataWriter_Helper_Uri', 'verifyUriOrEmpty')
				),
				'thumb_alt'						=> array('type' => self::TYPE_STRING, 'default' => ''),
				'image1_attachment_id'			=> array('type' => self::TYPE_UINT,    'default' => 0),
				'image1_crop_area'				=> array('type' => self::TYPE_SERIALIZED, 'default' => serialize(array())),
				'image1_caption'				=> array('type' => self::TYPE_STRING, 'default' => ''),
				'image1_url'					=> array('type' => self::TYPE_STRING, 'default' => '',
					'verification' => array('XenForo_DataWriter_Helper_Uri', 'verifyUriOrEmpty')
				),
				'image1_alt'					=> array('type' => self::TYPE_STRING, 'default' => ''),
				'image2_attachment_id'			=> array('type' => self::TYPE_UINT,    'default' => 0),
				'image2_crop_area'				=> array('type' => self::TYPE_SERIALIZED, 'default' => serialize(array())),
				'image2_caption'				=> array('type' => self::TYPE_STRING, 'default' => ''),
				'image2_url'					=> array('type' => self::TYPE_STRING, 'default' => '',
					'verification' => array('XenForo_DataWriter_Helper_Uri', 'verifyUriOrEmpty')
				),
				'image2_alt'					=> array('type' => self::TYPE_STRING, 'default' => ''),
				'image3_attachment_id'			=> array('type' => self::TYPE_UINT,    'default' => 0),
				'image3_crop_area'				=> array('type' => self::TYPE_SERIALIZED, 'default' => serialize(array())),
				'image3_caption'				=> array('type' => self::TYPE_STRING, 'default' => ''),
				'image3_url'					=> array('type' => self::TYPE_STRING, 'default' => '',
					'verification' => array('XenForo_DataWriter_Helper_Uri', 'verifyUriOrEmpty')
				),
				'image3_alt'					=> array('type' => self::TYPE_STRING, 'default' => ''),
				'image4_attachment_id'			=> array('type' => self::TYPE_UINT,    'default' => 0),
				'image4_crop_area'				=> array('type' => self::TYPE_SERIALIZED, 'default' => serialize(array())),
				'image4_caption'				=> array('type' => self::TYPE_STRING, 'default' => ''),
				'image4_url'					=> array('type' => self::TYPE_STRING, 'default' => '',
					'verification' => array('XenForo_DataWriter_Helper_Uri', 'verifyUriOrEmpty')
				),
				'image4_alt'					=> array('type' => self::TYPE_STRING, 'default' => ''),
				'competition_winners'			=> array('type' => self::TYPE_SERIALIZED, 'default' => serialize(array())),
			)
		);
	}

	/**
	 * 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, 'competition_id'))
		{
			return false;
		}

		return array('xf_avforums_competitions' => $this->_getCompetitionModel()->getCompetitionById($id));
	}

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

	protected function _preSave()
	{
		if (!$this->get('thumb_attachment_id'))
		{
			$this->error(new XenForo_Phrase('avforums_competitions_all_competitions_must_have_a_thumbnail'), 'thumb_attachment_id');
		}

		if ($this->isChanged('competition_state') && $this->getExisting('competition_state') == 'completed')
		{
			$this->set('competition_state', 'completed');
		}

		if (!$this->get('external_link') && !$this->get('competition_question'))
		{
			$this->error(new XenForo_Phrase('please_enter_value_for_required_field_x', array('field' => 'competition_question')));
		}
	}

	protected function _postSave()
	{
		$this->_updateActiveCompetitionCount();

		$hashes = $this->getExtraData(self::DATA_ALL_HASHES);
		$hashes = @unserialize($hashes);

		if ($hashes)
		{
			foreach ($hashes AS $type => $hash)
			{
				$this->_associateAttachments($hash, $type);
			}
		}

		if ($this->isUpdate() && $this->isChanged('competition_title'))
		{
			$threadDw = XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread', XenForo_DataWriter::ERROR_SILENT);
			if ($threadDw->setExistingData($this->get('competition_thread_id')) && $threadDw->get('discussion_type') == 'competition')
			{
				$threadDw->set('title', $this->get('competition_title'));
				$threadDw->save();
			}
		}

		if ($this->isUpdate() && $this->isChanged('competition_winners'))
		{
			$allWinners = @unserialize($this->get('competition_winners'));

			if ($allWinners)
			{
				foreach ($allWinners['winners'] AS $winner)
				{
					XenForo_Model_Alert::alert(
						$winner['user_id'],
						$winner['user_id'],
						$winner['username'],
						'avforums_competition',
						$this->get('competition_id'),
						'winner'
					);
				}

				foreach ($allWinners['runnersUp'] AS $runnerUp)
				{
					XenForo_Model_Alert::alert(
						$runnerUp['user_id'],
						$runnerUp['user_id'],
						$runnerUp['username'],
						'avforums_competition',
						$this->get('competition_id'),
						'runner_up'
					);
				}
			}
		}

		if ($this->isUpdate() && $this->isChanged('competition_state')
			&& $this->get('competition_state') == 'closed'
		)
		{
			XenForo_Model_Alert::alert(
				$this->get('user_id'),
				$this->get('user_id'),
				$this->get('username'),
				'avforums_competition',
				$this->get('competition_id'),
				'competition_closed'
			);
		}

		$insertThread = false;

		if ($this->isChanged('competition_state')
			&& $this->get('competition_state') == 'open'
			&& $this->get('competition_published') == 1
		)
		{
			$insertThread = true;
		}

		if ($this->isChanged('competition_published')
			&& $this->get('competition_published') == 1
			&& $this->get('competition_state') == 'open'
			&& $insertThread === false
		)
		{
			$insertThread = true;
		}

		if ($insertThread && !$this->get('competition_thread_id'))
		{
			$nodeId = $this->get('competition_node_id');
			if ($nodeId)
			{
				$threadId = $this->_insertDiscussionThread($nodeId);
				if ($threadId)
				{
					$this->set('competition_thread_id',
						$threadId, '', array('setAfterPreSave' => true)
					);

					$this->_db->update('xf_avforums_competitions', array('competition_thread_id' => $threadId),
						'competition_id = ' .  $this->_db->quote($this->get('competition_id'))
					);
				}
			}
		}
	}

	protected function _insertDiscussionThread($nodeId)
	{
		if (!$nodeId)
		{
			return false;
		}

		$forum = $this->getModelFromCache('XenForo_Model_Forum')->getForumById($nodeId);
		if (!$forum)
		{
			return false;
		}

		$threadDw = XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread', XenForo_DataWriter::ERROR_SILENT);
		$threadDw->setExtraData(XenForo_DataWriter_Discussion_Thread::DATA_FORUM, $forum);
		$threadDw->bulkSet(array(
			'node_id' => $nodeId,
			'title' => $this->get('competition_title'),
			'user_id' => $this->get('competition_thread_user_id')
				? $this->get('competition_thread_user_id')
				: $this->get('user_id'),
			'username' => $this->get('competition_thread_username')
				? $this->get('competition_thread_username')
				: $this->get('username'),
			'discussion_type' => 'competition'
		));
		$threadDw->set('discussion_state', $this->getModelFromCache('XenForo_Model_Post')->getPostInsertMessageState(array(), $forum));
		$threadDw->setOption(XenForo_DataWriter_Discussion::OPTION_PUBLISH_FEED, false);

		$message = $this->get('competition_text');

		$postWriter = $threadDw->getFirstMessageDw();
		$postWriter->set('message', $message);
		$postWriter->setExtraData(XenForo_DataWriter_DiscussionMessage_Post::DATA_FORUM, $forum);
		$postWriter->setOption(XenForo_DataWriter_DiscussionMessage::OPTION_PUBLISH_FEED, false);

		if (!$threadDw->save())
		{
			return false;
		}

		$this->set('competition_thread_id',
			$threadDw->get('thread_id'), '', array('setAfterPreSave' => true)
		);
		$postSaveChanges['competition_thread_id'] = $threadDw->get('thread_id');

		$this->getModelFromCache('XenForo_Model_Thread')->markThreadRead(
			$threadDw->getMergedData(), $forum, XenForo_Application::$time
		);

		$this->getModelFromCache('XenForo_Model_ThreadWatch')->setThreadWatchStateWithUserDefault(
			$this->get('user_id'), $threadDw->get('thread_id'),
			'watch_no_email'
		);

		return $threadDw->get('thread_id');
	}

	protected function _postDelete()
	{
		$competitionModel = $this->_getCompetitionModel();

		$attachmentIds = array(
			'thumb' => $this->get('thumb_attachment_id'),
			'image1' => $this->get('image1_attachment_id'),
			'image2' => $this->get('image2_attachment_id'),
			'image3' => $this->get('image3_attachment_id'),
			'image4' => $this->get('image4_attachment_id')
		);
		$attachments = $competitionModel->getAttachmentsByAttachmentIds($attachmentIds);

		$attachmentTypes = array();
		foreach ($attachmentIds AS $type => $attachmentId)
		{
			if (!empty($attachments[$attachmentId]))
			{
				$attachmentIds[$attachmentId] = array(
					'type' => $type,
					'attachment_id' => $attachmentId
				);
			}
		}

		foreach ($attachments AS $attachment)
		{
			$this->_db->update('xf_attachment', array(
				'unassociated' => 1
			), 'attachment_id = ' . $this->_db->quote($attachment['attachment_id']));

			@unlink ($competitionModel->getCompetitionImagePath($attachment, null, $attachmentIds[$attachment['attachment_id']]['type']));
		}

		if ($this->get('competition_thread_id'))
		{
			$threadDw = XenForo_DataWriter::create('XenForo_DataWriter_Discussion_Thread', XenForo_DataWriter::ERROR_SILENT);

			$threadDw->setExistingData($this->get('competition_thread_id'), true);
			$threadDw->delete();
		}
		
		if ($this->get('competition_enty_count') > 0) {

		    $entryModel = $this->_getEntryModel();
		    $entryDw = XenForo_DataWriter::create('AVForums_Competitions_DataWriter_Entry');
		        
		    $entries = $entryModel->getEntries(
		            array('competition_id' => $this->get('competition_id'))
		    );
		    
		    foreach ($entries as $entry) {
		        $entryDw->setExistingData($entry, true);
		        $entryDw->delete();
		    }
		}

		$this->_updateActiveCompetitionCount();
	}

	/**
	 * Associates attachments with this message.
	 *
	 * @param string $attachmentHash
	 */
	protected function _associateAttachments($attachmentHash, $type)
	{
		$this->_db->update('xf_attachment', array(
			'content_type' => 'avforums_competition',
			'content_id' => $this->get('competition_id'),
			'temp_hash' => '',
			'unassociated' => 0
		), 'temp_hash = ' . $this->_db->quote($attachmentHash));

		if (!$this->get($type . '_attachment_id'))
		{
			return false;
		}

		$attachmentModel = $this->_getAttachmentModel();
		$attachment = $attachmentModel->getAttachmentById($this->get($type . '_attachment_id'));

		$dataPath = $attachmentModel->getAttachmentDataFilePath($attachment);

		$image = new AVForums_Competitions_Helper_Image($dataPath);

		$imagePath = $attachmentModel->getAttachmentThumbnailFilePath($attachment);
		$imagePath = str_replace($attachment['file_hash'], $attachment['file_hash'] . '_' . $type, $imagePath);

		$options = XenForo_Application::get('options');

		$cropArea = @unserialize($this->get($type . '_crop_area'));

		foreach ($cropArea AS &$cropParam)
		{
			$cropParam = intval($cropParam);
		}

		if ($type == 'thumb')
		{
			$image->resizeCrop($options->get('competitionImageWidth'), $options->get('competitionImageHeight'), $cropArea['sel_x1'], $cropArea['sel_y1'], $cropArea['sel_width'], $cropArea['sel_height']);
		}
		else
		{
			if ($cropArea['sel_x1'] == 0
				&& $cropArea['sel_y1'] == 0
				&& $cropArea['sel_width'] == 0
				&& $cropArea['sel_height'] == 0
			)
			{
				$image->resizeTo($options->get('competitionImageWidth'), 0, 'maxwidth');
			}
			else
			{
				$image->resizeCrop($cropArea['sel_width'], $cropArea['sel_height'], $cropArea['sel_x1'], $cropArea['sel_y1'], $cropArea['sel_width'], $cropArea['sel_height']);
			}
		}

		$image->saveImage($imagePath);

		if ($type == 'thumb')
		{
			$smallPath = str_replace($attachment['file_hash'] . '_' . $type, $attachment['file_hash'] . '_' . $type . '_s', $imagePath);

			$smallImage = new AVForums_Competitions_Helper_Image($imagePath);

			$smallImage->resizeTo($options->get('competitionImageWidth') / 2, 0, 'maxwidth');
			$smallImage->saveImage($smallPath);
		}
	}

	protected function _updateActiveCompetitionCount()
	{
		$conditions = array(
			'competition_state' => 'open',
			'competition_published' => 1
		);
		$count = $this->_getCompetitionModel()->countCompetitions($conditions);

		XenForo_Application::setSimpleCacheData('competitionCount', $count);

		$this->_updateActiveCompetitionCache();
	}

	protected function _updateActiveCompetitionCache()
	{
		$options = XenForo_Application::get('options');

		if ($options->get('competitionSidebar'))
		{
			$competitionModel = $this->_getCompetitionModel();

			$conditions = array(
				'competition_state' => 'open',
				'force_thumbnail' => 1
			);
			$competitions = $competitionModel->getCompetitions($conditions);

			$conditions = array(
				'competition_state' => 'open',
				'force_thumbnail' => 0
			);
			$fetchOptions = array(
				'limit' => $options->get('competitionSidebar'),
				'order' => 'rand'
			);

			$competitions = $competitions + $competitionModel->getCompetitions($conditions, $fetchOptions);
			XenForo_Application::setSimpleCacheData('competitionsCacheFull', $competitions);

			$competitions = array_slice($competitions, 0, $options->get('competitionSidebar'), true);
			$competitions = $competitionModel->prepareCompetitions($competitions);

			XenForo_Application::setSimpleCacheData('competitionsCache', $competitions);
		}
	}

	protected function _validateStartDate(&$date)
	{
		if ($date === 0)
		{
			$this->error(new XenForo_Phrase('avforums_competitions_enter_valid_start_date'), 'competition_start');
			return false;
		}

		return true;
	}

	protected function _validateEndDate(&$date)
	{
		if ($date === 0)
		{
			$this->error(new XenForo_Phrase('avforums_competitions_enter_valid_end_date'), 'competition_end');
			return false;
		}

		return true;
	}

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

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