<?php

class AVForums_Competitions_ControllerPublic_Competition extends XenForo_ControllerPublic_Abstract
{
	/**
	 * Enforce view permissions for all actions in this controller
	 *
	 * @see library/XenForo/XenForo_Controller#_preDispatch($action)
	 */
	protected function _preDispatch($action)
	{
		if (!$this->_getCompetitionModel()->canViewCompetitions($error))
		{
			throw $this->getErrorOrNoPermissionResponseException($error);
		}
	}

	public function actionIndex()
	{
		$competitionModel = $this->_getCompetitionModel();

		$competitionId = $this->_input->filterSingle('competition_id', XenForo_Input::UINT);
		if ($competitionId)
		{
			return $this->responseReroute(__CLASS__, 'competition');
		}

		$conditions = array(
			'all' => $competitionModel->canViewAllCompetitions()
		);

		$fetchOptions = array(
			'join' => AVForums_Competitions_Model_Competition::FETCH_USER
				| AVForums_Competitions_Model_Competition::FETCH_ATTACHMENT
		);

		$competitions = $competitionModel->getCompetitions($conditions, $fetchOptions);
		$competitions = $competitionModel->prepareCompetitions($competitions);

		$viewParams = array(
			'competitions' => $competitions,
			'canCreate' => $competitionModel->canCreateCompetition()
		);

		return $this->responseView(
			'AVForums_Competitions_ViewPublic_Index',
			'avforums_competitions_index',
			$viewParams
		);
	}

	public function actionTerms()
	{
		$visitor = XenForo_Visitor::getInstance()->toArray();

		if ($this->isConfirmedPost())
		{
			if (!XenForo_Permission::hasPermission($visitor['permissions'], 'competitions', 'manageRules'))
			{
				throw $this->getNoPermissionResponseException();
			}

			$competitionTerms = $this->getHelper('Editor')->getMessageText('competition_terms', $this->_input);

			XenForo_Application::setSimpleCacheData('competitionTerms', $competitionTerms);

			return $this->responseRedirect(
				XenForo_ControllerResponse_Redirect::SUCCESS,
				XenForo_Link::buildPublicLink('competitions/terms'),
				new XenForo_Phrase('avforums_competitions_rules_updated_successfully')
			);
		}
		else
		{
			$viewParams = array(
				'canManage' => XenForo_Permission::hasPermission($visitor['permissions'], 'competitions', 'manageRules')
			);

			return $this->responseView(
				'AVForums_Competitions_ViewPublic_Terms',
				'avforums_competitions_terms',
				$viewParams
			);
		}
	}

	public function actionArchive()
	{
		$competitionModel = $this->_getCompetitionModel();
		if (!$competitionModel->canViewCompetitionsArchive($error))
		{
			throw $this->getErrorOrNoPermissionResponseException($error);
		}

		$page = max(1, $this->_input->filterSingle('page', XenForo_Input::UINT));
		$perPage = XenForo_Application::get('options')->get('competitionPerPage');

		$conditions = array(
			'all' => $competitionModel->canViewAllCompetitions()
		);

		$competitionsCount = $competitionModel->countCompetitions($conditions);

		$this->canonicalizePageNumber($page, $perPage, $competitionsCount, 'competitions/archive');
		$this->canonicalizeRequestUrl(
			XenForo_Link::buildPublicLink('competitions/archive', null, array('page' => $page))
		);

		$fetchOptions = array(
			'join' => AVForums_Competitions_Model_Competition::FETCH_USER
				| AVForums_Competitions_Model_Competition::FETCH_ATTACHMENT,
			'perPage' => $perPage,
			'page' => $page
		);

		$competitions = $competitionModel->getCompetitions($conditions, $fetchOptions);
		$competitions = $competitionModel->prepareCompetitions($competitions, true);

		foreach ($competitions AS &$competition)
		{
			$competition['competitionState'] = new XenForo_Phrase('avforums_competitions_' . $competition['competition_state']);
			if ($competition['competition_winners'])
			{
				$competition['competition_winners_count'] = count($competition['competition_winners']['winners']) + count($competition['competition_winners']['runnersUp']);
			}
		}

		$viewParams = array(
			'competitions' => $competitions,
			'page' => $page,
			'perPage' => $perPage,
			'startOffset' => ($page - 1) * $fetchOptions['perPage'] + 1,
			'endOffset' => ($page - 1) * $fetchOptions['perPage'] + count($competitions),
			'totalCompetitions' => $competitionsCount
		);

		return $this->responseView(
			'AVForums_Competitions_ViewPublic_Archive',
			'avforums_competitions_archive',
			$viewParams
		);
	}

	public function actionEntries()
	{
		$entryModel = $this->_getEntryModel();
		$competitionModel = $this->_getCompetitionModel();

		if (!$competitionModel->canViewCompetitionsArchive($error))
		{
			throw $this->getErrorOrNoPermissionResponseException($error);
		}

		$competitionId = $this->_input->filterSingle('competition_id', XenForo_Input::UINT);
		$competition = $this->_assertCompetitionValidAndViewable($competitionId);
		
		$changeResult = $this->_input->filterSingle('c', XenForo_Input::UINT);
		$removeEntry = $this->_input->filterSingle('r', XenForo_Input::UINT);
		
		if (!empty($changeResult)) {
		    $entry = $this->_getEntryModel()->getEntryById($changeResult);
			$dw = XenForo_DataWriter::create('AVForums_Competitions_DataWriter_Entry');
			$dw->setExistingData($entry, true);
			$updateString = substr($dw->get('answer_state'), 0, 2) == 'in' ? 'correct' : 'incorrect';
			$dw->set('answer_state', $updateString);
			$dw->save();
		}
		
		if (!empty($removeEntry)) {
		    //$entry = $entries[$removeEntry];
		    $entry = $this->_getEntryModel()->getEntryById($removeEntry);
			$dw = XenForo_DataWriter::create('AVForums_Competitions_DataWriter_Entry');
			$dw->setExistingData($entry, true);
			$dw->delete();
		}
		
		if (!empty($entry)) {
			// Redirect to attachment listing
			return $this->responseRedirect(
				XenForo_ControllerResponse_Redirect::SUCCESS,
				XenForo_Link::buildPublicLink('competitions/entries', $competition)
			);
		}

		$entries = $entryModel->getEntries(
			array('competition_id' => $competitionId),
			array('join' => AVForums_Competitions_Model_Entry::FETCH_USER)
		);

		$viewParams = array(
			'competition' => $competition,
			'entries' => $entries
		);

		return $this->responseView(
			'AVForums_Competitions_ViewPublic_Entries',
			'avforums_competitions_entries',
			$viewParams
		);
	}

	public function actionOptins()
	{
		$competitionId = $this->_input->filterSingle('competition_id', XenForo_Input::UINT);
		$competition = $this->_assertCompetitionValidAndViewable($competitionId);

		if (!$this->_getCompetitionModel()->canDownloadCompetitionOptIns($error))
		{
			throw $this->getErrorOrNoPermissionResponseException($error);
		}

		$entryModel = $this->_getEntryModel();

		$this->_routeMatch->setResponseType('raw');

		$optIns = $entryModel->getOptInsByCompetitionId($competitionId);

		$viewParams = array(
			'competition' => $competition,
			'optIns' => $optIns
		);

		return $this->responseView(
			'AVForums_Competitions_ViewPublic_Download',
			'',
			$viewParams
		);
	}

	public function actionWinners()
	{
		$competitionModel = $this->_getCompetitionModel();

		if (!$competitionModel->canViewCompetitionsArchive($error))
		{
			throw $this->getErrorOrNoPermissionResponseException($error);
		}

		$competitionId = $this->_input->filterSingle('competition_id', XenForo_Input::UINT);
		$competition = $this->_assertCompetitionValidAndViewable($competitionId);

		$viewParams = array(
			'competitionWinners' => $competition['competition_winners'],
			'canDownloadWinners' => $competitionModel->canDownloadCompetitionWinners(),
			'competition' => $competition
		);

		return $this->responseView(
			'AVForums_Competitions_ViewPublic_Winners',
			'avforums_competitions_winners',
			$viewParams
		);
	}

	public function actionWinnersDownload()
	{
		$competitionId = $this->_input->filterSingle('competition_id', XenForo_Input::UINT);
		$competition = $this->_assertCompetitionValidAndViewable($competitionId);

		if (!$this->_getCompetitionModel()->canDownloadCompetitionWinners($error))
		{
			throw $this->getErrorOrNoPermissionResponseException($error);
		}

		$entryModel = $this->_getEntryModel();

		$this->_routeMatch->setResponseType('raw');

		$winners = $entryModel->getWinnersByCompetitionId($competitionId);

		$viewParams = array(
			'competition' => $competition,
			'winners' => $winners
		);

		return $this->responseView(
			'AVForums_Competitions_ViewPublic_Download',
			'',
			$viewParams
		);
	}

	public function actionCompetition()
	{   
		$competitionId = $this->_input->filterSingle('competition_id', XenForo_Input::UINT);
		$competition = $this->_assertCompetitionValidAndViewable($competitionId);

		$competitionModel = $this->_getCompetitionModel();

		// This shouldn't be necessary. But at least we're now certain the correct answer isn't available to the template.
		if ($competition['competition_state'] != 'completed') {
		    unset ($competition['competition_answers']['correct_answer']);
		}

		$this->canonicalizeRequestUrl(XenForo_Link::buildPublicLink('competitions', $competition));

		$canEnter = $competitionModel->canEnterCompetition($competition, $denyEnterReason);

		$registeredCanEnter = false;
		if (in_array('-1', $competition['enter_user_groups']) || in_array('2', $competition['enter_user_groups']))
		{
			$registeredCanEnter = true;
		}

		$showSideBar = false;
		if (($competition['thumbnailUrl'] && XenForo_Application::get('options')->competitionShowThumb)
			|| $competition['image1Url']
			|| $competition['image2Url']
			|| $competition['image3Url']
			|| $competition['image4Url']
		)
		{
			$showSideBar = true;
		}
		
		// get visitor language
		$visitorLanguage = XenForo_Visitor::getInstance()->getLanguage();
        setlocale(LC_TIME, preg_replace('/\-/', '_', $visitorLanguage['language_code']));
        unset( $visitorLanguage );
		
		// Set date string to english or international
		$dateFormat = XenForo_Application::get('options')->get('competitionDateFormat');
		
		$entryDate = '';
		if ($denyEnterReason == 'has_entered')
		{
		    $theEntry = $this->_getEntryModel()->getEntries(array(
		            'competition_id' => $competitionId,
		            'user_id' => XenForo_Visitor::getUserId()
		    ));
		    $theEntry = array_pop($theEntry);
		    $entryDate = strftime($dateFormat, $theEntry['entry_date']);
		    unset($theEntry);
		}

		$viewParams = array(
			'competition' => $competition,
			'endDate' => strftime($dateFormat, $competition['competition_end']),
			'startDate' => strftime($dateFormat, $competition['competition_start']),
			'entryDate' => $entryDate,
			'territoryStrings' => $competitionModel->getTerritoriesForList(),
			'canEnter' => $canEnter,
			'denyEnterReason' => $denyEnterReason,
			'registeredCanEnter' => $registeredCanEnter,
			'competitionType' => $competition['competition_type'] == 'competition' ? new XenForo_Phrase('avforums_competitions_competition') : new XenForo_Phrase('avforums_competitions_prize_draw'),
			'submitButton' => new XenForo_Phrase('avforums_competitions_enter_' . $competition['competition_type']),
			'thread' => $competition['competition_thread_id']
				? $this->_getThreadModel()->getThreadById($competition['competition_thread_id'])
				: false,
			'selectedTab' => 'enter',
			'showSidebar' => $showSideBar
		);

		return $this->responseView(
			'AVForums_Competitions_ViewPublic_View',
			'avforums_competitions_view',
			$viewParams
		);
	}

	protected function _assertCompetitionValidAndViewable($competitionId, $fetchOptions = array())
	{
		$competition = $this->_getCompetitionOrError($competitionId);

		$competitionModel = $this->_getCompetitionModel();
		if (!$competitionModel->canViewAllCompetitions($error) && $competition['competition_published'] == 0)
		{
			throw $this->getErrorOrNoPermissionResponseException('avforums_competitions_error_' . $error);
		}

		$competition = $competitionModel->prepareCompetition($competition);
		$competitionModel->logCompetitionView($competition);

		return $competition;
	}

	protected function _assertCompetitionEditable(array $competition)
	{
		$competitionModel = $this->_getCompetitionModel();
		if (!$competitionModel->canEditCompetition($competition, $error))
		{
			throw $this->getErrorOrNoPermissionResponseException($error);
		}
	}

	protected function _assertCompetitionDeletable(array $competition)
	{
		$competitionModel = $this->_getCompetitionModel();
		if (!$competitionModel->canDeleteCompetition($competition, $error))
		{
			throw $this->getErrorOrNoPermissionResponseException($error);
		}
	}

	public function actionDob()
	{
		$this->_assertPostOnly();

		if (!XenForo_Visitor::getInstance()->canEditProfile())
		{
			return $this->responseNoPermission();
		}

		$settings = $this->_input->filter(array(
			'dob_day'    => XenForo_Input::UINT,
			'dob_month'  => XenForo_Input::UINT,
			'dob_year'   => XenForo_Input::UINT,
			'show_dob_year' => XenForo_Input::UINT,
			'show_dob_date' => XenForo_Input::UINT
		));

		$visitor = XenForo_Visitor::getInstance();
		if ($visitor['dob_day'] && $visitor['dob_month'] && $visitor['dob_year'])
		{
			// can't change dob if set
			unset($settings['dob_day'], $settings['dob_month'], $settings['dob_year']);
		}

		$writer = XenForo_DataWriter::create('XenForo_DataWriter_User');
		$writer->setExistingData(XenForo_Visitor::getUserId());
		$writer->bulkSet($settings);

		$writer->preSave();

		if ($dwErrors = $writer->getErrors())
		{
			return $this->responseError($dwErrors);
		}

		$writer->save();

		return $this->responseRedirect(
			XenForo_ControllerResponse_Redirect::SUCCESS,
			$this->getDynamicRedirect(),
			new XenForo_Phrase('avforums_competitions_thank_you_for_setting_your_dob')
		);
	}

	public function actionCreate()
	{
		return $this->_getCompetitionCreateEditResponse($this->_getDefaultCompetition());
	}

	public function actionEdit()
	{
		$competitionId = $this->_input->filterSingle('competition_id', XenForo_Input::UINT);
		$competition = $this->_getCompetitionOrError($competitionId);

		$this->_assertCompetitionEditable($competition);

		$competition = $this->_getCompetitionModel()->prepareCompetition($competition);

		$competition['thumb_crop_area'] = @unserialize($competition['thumb_crop_area']);

		$this->canonicalizeRequestUrl(XenForo_Link::buildPublicLink('competitions/edit', $competition));

		return $this->_getCompetitionCreateEditResponse($competition);
	}

	protected function _getCompetitionCreateEditResponse(array $competition)
	{
		$competitionModel = $this->_getCompetitionModel();

		$userGroups = $this->getModelFromCache('XenForo_Model_UserGroup')->getAllUserGroups();

		$viewUserGroups = $competition['view_user_groups'];
		$enterUserGroups = $competition['enter_user_groups'];

		$thumbnailId = 'ThumbnailFile_' . md5(uniqid('', true));
		$image1Id = 'Image1File_' . md5(uniqid('', true));
		$image2Id = 'Image2File_' . md5(uniqid('', true));
		$image3Id = 'Image3File_' . md5(uniqid('', true));
		$image4Id = 'Image4File_' . md5(uniqid('', true));

		if ($username = XenForo_Application::get('options')->get('competitionThreadUsername'))
		{
			/** @var $userModel XenForo_Model_User */
			$userModel = $this->getModelFromCache('XenForo_Model_User');

			$threadUser = $userModel->getUserByName($username);
		}
		else
		{
			$threadUser = array(
				'user_id' => $competition['competition_thread_user_id'],
				'username' => $competition['competition_thread_username']
			);
		}

		$viewParams = array(
			'competition' => $competition,

			'geoIp' => function_exists('geoip_country_code_by_name'),

			'territories' => $competitionModel->getTerritoriesForList(),
			'userGroups' => $userGroups,
			'viewUserGroups' => $viewUserGroups ? $viewUserGroups : array('-1'),
			'enterUserGroups' => $enterUserGroups ? $enterUserGroups : array('-1'),

			'canPublish' => $competitionModel->canPublishCompetition($competition),

			'nodes' => $this->_getNodeModel()->getViewableNodeList(null, true),

			'imageParams' => array(
				$thumbnailId => $competitionModel->getCompetitionAttachmentParams(),
				$image1Id => $competitionModel->getCompetitionAttachmentParams(),
				$image2Id => $competitionModel->getCompetitionAttachmentParams(),
				$image3Id => $competitionModel->getCompetitionAttachmentParams(),
				$image4Id => $competitionModel->getCompetitionAttachmentParams()
			),
			'imageConstraints' => array(
				$thumbnailId => $competitionModel->getCompetitionAttachmentConstraints(),
				$image1Id => $competitionModel->getCompetitionAttachmentConstraints(),
				$image2Id => $competitionModel->getCompetitionAttachmentConstraints(),
				$image3Id => $competitionModel->getCompetitionAttachmentConstraints(),
				$image4Id => $competitionModel->getCompetitionAttachmentConstraints()
			),

			'thumbnailId' => $thumbnailId,
			'image1Id' => $image1Id,
			'image2Id' => $image2Id,
			'image3Id' => $image3Id,
			'image4Id' => $image4Id,

			'thread' => $competition['competition_thread_id']
				? $this->_getThreadModel()->getThreadById($competition['competition_thread_id'])
				: false,

			'threadUser' => $threadUser
		);

		return $this->responseView(
			'AVForums_Competitions_ViewPublic_Create',
			'avforums_competitions_create',
			$viewParams
		);
	}

	public function actionDelete()
	{
		$competitionId = $this->_input->filterSingle('competition_id', XenForo_Input::UINT);
		$competition = $this->_getCompetitionOrError($competitionId);

		$this->_assertCompetitionDeletable($competition);

		if ($this->isConfirmedPost())
		{
			$competitionWriter = XenForo_DataWriter::create('AVForums_Competitions_DataWriter_Competition');

			$competitionWriter->setExistingData($competitionId);
			$competitionWriter->delete();
		}
		else
		{
			$viewParams = array(
				'competition' => $competition
			);

			return $this->responseView(
				'AVForums_Competitions_ViewPublic_Delete',
				'avforums_competitions_delete',
				$viewParams
			);
		}

		return $this->responseRedirect(
			XenForo_ControllerResponse_Redirect::SUCCESS,
			XenForo_Link::buildPublicLink('competitions'),
			new XenForo_Phrase('avforums_competitions_competition_deleted_successfully')
		);
	}

	public function actionQuickUpdate()
	{
		$this->_assertPostOnly();
		$this->_assertRegistrationRequired();

		$competitionId = $this->_input->filterSingle('competition_id', XenForo_Input::UINT);

		$competition = $this->_getCompetitionOrError($competitionId);

		$competitionModel = $this->_getCompetitionModel();

		$input = $this->_input->filter(array(
			'competition_state' => XenForo_Input::UINT,
			'competition_published' => XenForo_Input::UINT,
		));

		$set = $this->_input->filterSingle('set', XenForo_Input::ARRAY_SIMPLE, array('array' => true));

		$dwInput = array();

		if (isset($set['competition_state']) && ($competitionModel->canOpenCompetition($competition)))
		{
			$dwInput['competition_state'] = $input['competition_state'] ? 'open' : 'closed';
		}

		if (isset($set['competition_published']) && ($competitionModel->canPublishCompetition($competition)))
		{
			$dwInput['competition_published'] = $input['competition_published'];
		}

		if ($dwInput)
		{
			$dw = XenForo_DataWriter::create('AVForums_Competitions_DataWriter_Competition');
			$dw->setExistingData($competitionId);
			$dw->bulkSet($dwInput);
			$dw->save();
		}

		return $this->responseRedirect(
			XenForo_ControllerResponse_Redirect::SUCCESS,
			XenForo_Link::buildPublicLink('competitions', $competition)
		);
	}

	public function actionImageDelete()
	{
		$csrfToken = $this->_input->filterSingle('_xfToken', XenForo_Input::STRING);

		$attachmentId = $this->_input->filterSingle('attachment_id', XenForo_Input::UINT);
		$type = $this->_input->filterSingle('type', XenForo_Input::STRING);

		$competitionId = $this->_input->filterSingle('competition_id', XenForo_Input::UINT);

		if (!$csrfToken || !$attachmentId || !$type || !$competitionId)
		{
			return $this->responseRedirect(
				XenForo_ControllerResponse_Redirect::SUCCESS,
				$this->getDynamicRedirect()
			);
		}
		$this->_checkCsrfFromToken($csrfToken);

		$competition = $this->_getCompetitionOrError($competitionId);
		$attachment = $this->_getAttachmentModel()->getAttachmentById($attachmentId);

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

		$competitionData = array(
			$type . '_attachment_id' => 0,
			$type . '_crop_area' => serialize(array())
		);

		if ($competition[$type . '_attachment_id'] != $attachment['attachment_id'])
		{
			return $this->getNoPermissionResponseException();
		}

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

		$attachmentWriter = XenForo_DataWriter::create('XenForo_DataWriter_Attachment');
		$attachmentWriter->setExistingData($attachment, true);
		$attachmentWriter->delete();

		return $this->responseRedirect(
			XenForo_ControllerResponse_Redirect::SUCCESS,
			$this->getDynamicRedirect(),
			new XenForo_Phrase('avforums_competitions_image_deleted_successfully')
		);
	}

	public function actionEntry()
	{
		$this->_assertRegistrationRequired();
		$this->_assertPostOnly();

		$competitionId = $this->_input->filterSingle('competition_id', XenForo_Input::UINT);

		$competition = $this->_getCompetitionOrError($competitionId);
		$competition = $this->_getCompetitionModel()->prepareCompetition($competition);

		$givenAnswerId = $this->_input->filterSingle('given_answer', XenForo_Input::STRING);

		if ($givenAnswerId === '')
		{
			throw $this->getErrorOrNoPermissionResponseException('avforums_competitions_you_must_give_an_answer');
		}

		$correctAnswerId = array_shift($competition['competition_answers']['correct_answer']);
		$correctAnswerText = $competition['competition_answers']['answers'][$correctAnswerId];

		if ($this->_input->filterSingle('text_answer', XenForo_Input::UINT))
		{
			$givenAnswerText = strtolower($givenAnswerId);
		}
		else
		{
			$givenAnswerText = strtolower($competition['competition_answers']['answers'][$givenAnswerId]);
		}

		$entryData = array();
		$entryData['given_answer'] = $givenAnswerText;

		if (strtolower($givenAnswerText) == strtolower($correctAnswerText))
		{
			$entryData['answer_state'] = 'correct';
		}
		else
		{
			$entryData['answer_state'] = 'incorrect';
		}

		$entryData['answer_state_original'] = $entryData['answer_state'];

		$visitor = XenForo_Visitor::getInstance();

		$entryData = $entryData + array(
			'user_id' => $visitor->get('user_id'),
			'username' => $visitor->get('username'),
			'competition_id' => $competitionId,
			'opt_in' => $this->_input->filterSingle('opt_in', XenForo_Input::UINT)
		);

		$entryWriter = XenForo_DataWriter::create('AVForums_Competitions_DataWriter_Entry');

		$entryWriter->bulkSet($entryData);
		$entryWriter->save();

		return $this->responseRedirect(
			XenForo_ControllerResponse_Redirect::SUCCESS,
			XenForo_Link::buildPublicLink('competitions', $competition),
			new XenForo_Phrase('avforums_competitions_thank_you_for_your_entry')
		);
	}

	public function actionSave()
	{
		$this->_assertPostOnly();

		$competitionModel = $this->_getCompetitionModel();

		$competitionId = $this->_input->filterSingle('competition_id', XenForo_Input::UINT);
		$competition = $competitionModel->getCompetitionById($competitionId);

		$visitor = XenForo_Visitor::getInstance();

		$competitionData = $this->_input->filter(array(
			// Basic Details
			'competition_title' => XenForo_Input::STRING,
			'competition_type' => XenForo_Input::STRING,
			'competition_prize' => XenForo_Input::STRING,
			'prize_value' => XenForo_Input::FLOAT,
			'number_of_winners' => XenForo_Input::UINT,
			'number_of_runners_up' => XenForo_Input::UINT,
			'sponsor' => XenForo_Input::STRING,
			'external_link' => XenForo_Input::STRING,

			// Question & Answer
			'competition_question' => XenForo_Input::STRING,

			// Restrictions & Conditions
			'minimum_age' => XenForo_Input::UINT,
			'territories' => array(XenForo_Input::STRING, array('array' => true)),
			'usable_view_user_group_type' => XenForo_Input::STRING,
			'usable_enter_user_group_type' => XenForo_Input::STRING,
			'view_user_group_ids' => array(XenForo_Input::UINT, 'array' => true),
			'enter_user_group_ids' => array(XenForo_Input::UINT, 'array' => true),

			// Options
			'competition_images_left' => XenForo_Input::UINT,
			'competition_opt_out' => XenForo_Input::UINT,
			'force_thumbnail' => XenForo_Input::UINT,
			'competition_hide_form' => XenForo_Input::UINT,
			'competition_node_id' => XenForo_Input::UINT
		));

		$cropAreas = $this->_input->filterSingle('sel_data', XenForo_Input::ARRAY_SIMPLE);

		$competitionData = $competitionData + array(
			'thumb_crop_area' => $cropAreas['thumb'],
			'image1_crop_area' => $cropAreas['image1'],
			'image2_crop_area' => $cropAreas['image2'],
			'image3_crop_area' => $cropAreas['image3'],
			'image4_crop_area' => $cropAreas['image4'],
		);

		if ($competitionData['usable_view_user_group_type'] == 'all')
		{
			$allowedViewGroupIds = array('-1'); // -1 is a sentinel for all groups
		}
		else
		{
			$allowedViewGroupIds = $competitionData['view_user_group_ids'];
		}

		if ($competitionData['usable_enter_user_group_type'] == 'all')
		{
			$allowedEnterGroupIds = array('-1'); // -1 is a sentinel for all groups
		}
		else
		{
			$allowedEnterGroupIds = $competitionData['enter_user_group_ids'];
		}

		$competitionData['view_user_groups'] = $allowedViewGroupIds;
		$competitionData['enter_user_groups'] = $allowedEnterGroupIds;

		if (!function_exists('geoip_country_code_by_name'))
		{
			$competitionData['territories'] = array('-1');
		}

		unset ($competitionData['usable_view_user_group_type'], $competitionData['usable_enter_user_group_type'], $competitionData['view_user_group_ids'], $competitionData['enter_user_group_ids']);

		$answers = $this->_input->filterSingle('competition_answer', XenForo_Input::STRING, array('array' => true));
		array_unshift($answers, null);
		unset ($answers[0]);
		$correctAnswer = $this->_input->filterSingle('correct_answer', XenForo_Input::UINT, array('array' => true));

		$answers = array_filter($answers);

		if (!$competitionData['external_link'] && (!$correctAnswer || !$answers))
		{
			throw $this->responseException($this->responseError(new XenForo_Phrase('avforums_competitions_competition_must_have_one_answer')));
		}

		if (!$competitionData['external_link'])
		{
			$competitionData['competition_answers'] = array(
				'answers' => $answers,
				'correct_answer' => array(
					$correctAnswer[0] => $correctAnswer[0]
				)
			);
		}

		$open = $this->_input->filterSingle('competition_open', XenForo_Input::UINT);
		$publish = $this->_input->filterSingle('competition_published', XenForo_Input::UINT);

		$canOpen = false;
		if ($competition)
		{
			$canOpen = $competitionModel->canOpenCompetition($competition);
		}
		else
		{
			if (XenForo_Permission::hasPermission($visitor->get('permissions'), 'competitions', 'openAnyCompetition')
				|| XenForo_Permission::hasPermission($visitor->get('permissions'), 'competitions', 'openOwnCompetition')
			)
			{
				$canOpen = true;
			}
		}

		$canPublish = false;
		if ($competition)
		{
			$canPublish = $competitionModel->canPublishCompetition($competition);
		}
		else
		{
			if (XenForo_Permission::hasPermission($visitor->get('permissions'), 'competitions', 'publishAnyCompetition')
				|| XenForo_Permission::hasPermission($visitor->get('permissions'), 'competitions', 'publishOwnCompetition')
			)
			{
				$canPublish = true;
			}
		}

		if ($canOpen)
		{
			if ($open)
			{
				$competitionData['competition_state'] = 'open';
			}
			else
			{
				$competitionData['competition_state'] = 'closed';
			}
		}
		else
		{
			if ($competition)
			{
				$competitionData['competition_state'] = $competition['competition_state'];
			}
			else
			{
				$competitionData['competition_state'] = 'closed';
			}
		}

		if ($canPublish)
		{
			if ($publish)
			{
				$competitionData['competition_published'] = 1;
			}
			else
			{
				$competitionData['competition_published'] = 0;
			}
		}
		else
		{
			if ($competition)
			{
				$competitionData['competition_published'] = $competition['competition_published'];
			}
			else
			{
				$competitionData['competition_published'] = 0;
			}
		}

		$competitionData['competition_start'] = strtotime(
		        $this->_input->filterSingle('competition_start', XenForo_Input::STRING) . ' ' .
				$this->_input->filterSingle('competition_start_time', XenForo_Input::STRING) );

		$competitionData['competition_end'] = strtotime(
		        $this->_input->filterSingle('competition_end', XenForo_Input::STRING) . ' ' .
				$this->_input->filterSingle('competition_end_time', XenForo_Input::STRING) );

		$attachmentHashes = $this->_input->filterSingle('file_hash', XenForo_Input::ARRAY_SIMPLE);

		$attachmentModel = $this->_getAttachmentModel();

		$attachments = array();
		foreach ($attachmentHashes AS $type => $attachmentHash)
		{
			$attachment = $attachmentModel->getAttachmentsByTempHash($attachmentHash);

			if (!$attachment)
			{
				unset ($attachmentHashes[$type]);

				continue;
			}

			$attachments[$type] =  array_shift($attachment);
		}

		$editorHelper = $this->getHelper('Editor');

		$competitionData = $competitionData + array(
			// Editor text
			'competition_text' => $editorHelper->getMessageText('competition_text', $this->_input),
			'question_hint' => $editorHelper->getMessageText('question_hint', $this->_input),
			'restrictions' => $editorHelper->getMessageText('restrictions', $this->_input),
			'marketing_message' => $editorHelper->getMessageText('marketing_message', $this->_input),
			'submit_text' => $editorHelper->getMessageText('submit_text', $this->_input),

			// Visitor
			'user_id' => $visitor->get('user_id'),
			'username' => $visitor->get('username')
		);

		$competitionWriter = XenForo_DataWriter::create('AVForums_Competitions_DataWriter_Competition');

		if ($competitionId)
		{
			$competitionWriter->setExistingData($competitionId);

			foreach ($attachments AS $type => $attachment)
			{
				if ($this->_input->filterSingle('new_' . $type, XenForo_Input::UINT))
				{
					$competitionData[$type . '_attachment_id'] = $attachment['attachment_id'];
					$competitionWriter->setExtraData(AVForums_Competitions_DataWriter_Competition::DATA_ALL_HASHES, serialize($attachmentHashes));
				}
				else
				{
					$competitionData[$type . '_attachment_id'] = $competitionWriter->get($type . '_attachment_id');
				}
			}
		}
		else
		{
			foreach ($attachments AS $type => $attachment)
			{
				if ($this->_input->filterSingle('new_' . $type, XenForo_Input::UINT))
				{
					$competitionData[$type . '_attachment_id'] = $attachment['attachment_id'];
					$competitionWriter->setExtraData(AVForums_Competitions_DataWriter_Competition::DATA_ALL_HASHES, serialize($attachmentHashes));
				}

				$competitionData[$type . '_caption'] = $editorHelper->getMessageText($type . '_caption', $this->_input);
				$competitionData[$type . '_url'] = $this->_input->filterSingle($type . '_url', XenForo_Input::STRING);
			}
		}

		$user = array();

		/** @var $userModel XenForo_Model_User */
		$userModel = $this->getModelFromCache('XenForo_Model_User');

		$username = $this->_input->filterSingle('competition_thread_username', XenForo_Input::STRING);
		if ($username)
		{
			$user = $userModel->getUserByName($username);

			if (!$user)
			{
				return $this->responseError(new XenForo_Phrase('requested_member_not_found'), 404);
			}
		}
		
		$competitionData = $competitionData + array(
			'competition_thread_user_id' => $user ? $user['user_id'] : 0,
			'competition_thread_username' => $user ? $user['username'] : '',

			'thumb_caption' => $editorHelper->getMessageText('thumb_caption', $this->_input),
			'thumb_url' => $this->_input->filterSingle('thumb_url', XenForo_Input::STRING),
			'thumb_alt' => $this->_input->filterSingle('thumb_alt', XenForo_Input::STRING),

			'image1_caption' => $editorHelper->getMessageText('image1_caption', $this->_input),
			'image1_url' => $this->_input->filterSingle('image1_url', XenForo_Input::STRING),
			'image1_alt' => $this->_input->filterSingle('image1_alt', XenForo_Input::STRING),

			'image2_caption' => $editorHelper->getMessageText('image2_caption', $this->_input),
			'image2_url' => $this->_input->filterSingle('image2_url', XenForo_Input::STRING),
			'image2_alt' => $this->_input->filterSingle('image2_alt', XenForo_Input::STRING),

			'image3_caption' => $editorHelper->getMessageText('image3_caption', $this->_input),
			'image3_url' => $this->_input->filterSingle('image3_url', XenForo_Input::STRING),
			'image3_alt' => $this->_input->filterSingle('image3_alt', XenForo_Input::STRING),

			'image4_caption' => $editorHelper->getMessageText('image4_caption', $this->_input),
			'image4_url' => $this->_input->filterSingle('image4_url', XenForo_Input::STRING),
			'image4_alt' => $this->_input->filterSingle('image4_alt', XenForo_Input::STRING),
		);
		
		$competitionWriter->bulkSet($competitionData);
		$competitionWriter->save();

		return $this->responseRedirect(
			XenForo_ControllerResponse_Redirect::SUCCESS,
			XenForo_Link::buildPublicLink('competitions'),
			$competitionId ?
				new XenForo_Phrase('avforums_competitions_competition_updated_successfully') :
				new XenForo_Phrase('avforums_competitions_competition_created_successfully')
		);
	}

	public static function getSessionActivityDetailsForList(array $activities)
	{
		$competitionIds = array();
		foreach ($activities AS $activity)
		{
			if (!empty($activity['params']['competition_id']))
			{
				$competitionIds[$activity['params']['competition_id']] = intval($activity['params']['competition_id']);
			}
		}

		$competitionData = array();

		if ($competitionIds)
		{
			/* @var $competitionModel AVForums_Competitions_Model_Competition */
			$competitionModel = XenForo_Model::create('AVForums_Competitions_Model_Competition');

			$competitions = $competitionModel->getCompetitions(array('competition_id' => $competitionIds));
			foreach ($competitions AS $competition)
			{
				$competitionData[$competition['competition_id']] = array(
					'title' => $competition['competition_title'],
					'url' => XenForo_Link::buildPublicLink('competitions', $competition)
				);
			}
		}

		$output = array();
		foreach ($activities AS $key => $activity)
		{
			$competition = false;
			if (!empty($activity['params']['competition_id']))
			{
				$competitionId = $activity['params']['competition_id'];
				if (isset($competitionData[$competitionId]))
				{
					$competition = $competitionData[$competitionId];
				}
			}

			if ($competition)
			{
				$output[$key] = array(
					new XenForo_Phrase('avforums_competitions_viewing_competition'),
					$competition['title'],
					$competition['url'],
					''
				);
			}
			else
			{
				$output[$key] = new XenForo_Phrase('avforums_competitions_viewing_competition');
			}
		}

		return $output;
	}

	protected function _getDefaultCompetition()
	{
		$visitor = XenForo_Visitor::getInstance();

		return array(
			'competition_id' => 0,
			'competition_thread_id' => 0,
			'competition_type' => 'competition',
			'competition_text' => '',
			'competitionStart' => date('Y-m-d', XenForo_Application::$time),
			'competitionEnd' => date('Y-m-d', XenForo_Application::$time + (86400 * 7)),
			'competitionStartTime' => '00:00',
			'competitionEndTime' => '00:00',
			'number_of_winners' => 1,
			'number_of_runners_up' => 0,
			'canOpen' => XenForo_Permission::hasPermission($visitor->get('permissions'), 'competitions', 'openOwnCompetition') ||
				XenForo_Permission::hasPermission($visitor->get('permissions'), 'competitions', 'openAnyCompetition'),
			'canPublish' => XenForo_Permission::hasPermission($visitor->get('permissions'), 'competitions', 'publishOwnCompetition') ||
				XenForo_Permission::hasPermission($visitor->get('permissions'), 'competitions', 'publishAnyCompetition'),
			'question_hint' => '',
			'minimum_age' => 18,
			'territories' => array('-1'),
			'view_user_groups' => array('-1'),
			'enter_user_groups' => array('-1'),
			'restrictions' => '',
			'marketing_message' => '',
			'competition_thread_id' => 0,
			'competition_thread_user_id' => 0,
			'competition_thread_username' => '',
			'submit_text' => '',
			'thumb_caption' => '',
			'image1_caption' => '',
			'image2_caption' => '',
			'image3_caption' => '',
			'image4_caption' => ''
		);
	}

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

		$competition = $competitionModel->getCompetitionById($competitionId, array('join' => AVForums_Competitions_Model_Competition::FETCH_ATTACHMENT));
		if (!$competition)
		{
			throw $this->responseException($this->responseError(new XenForo_Phrase('avforums_competitions_competition_not_found'), 404));
		}

		return $competition;
	}

	/**
	 * @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');
	}

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

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

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