<?php

namespace XF\Job;

use XF\Entity\Forum;
use XF\Entity\Thread;
use XF\Finder\ThreadFinder;

use function count;

class ForumChangeThreadTypes extends AbstractJob
{
	protected $defaultData = [
		'node_id' => null,
		'old_default_type' => null,

		'count' => 0,
		'last' => 0,
		'total' => null,
	];

	public function run($maxRunTime)
	{
		$s = microtime(true);

		if (!$this->data['node_id'])
		{
			throw new \InvalidArgumentException('Cannot change forum thread types without a node_id.');
		}

		/** @var Forum $forum */
		$forum = $this->app->find(Forum::class, $this->data['node_id']);
		if (!$forum)
		{
			return $this->complete();
		}

		$typeHandler = $forum->TypeHandler;
		$newDefaultType = $typeHandler->getDefaultThreadType($forum);

		$allowedThreadTypes = $typeHandler->getExtraAllowedThreadTypes($forum);
		$allowedThreadTypes[] = $newDefaultType;
		$allowedThreadTypes[] = 'redirect'; // redirects are always allowed, so never change them

		$threadFinder = $this->app->finder(ThreadFinder::class)
			->where('node_id', $this->data['node_id'])
			->where('discussion_type', '<>', $allowedThreadTypes)
			->order('thread_id');

		if ($this->data['total'] === null)
		{
			$this->data['total'] = $threadFinder->total();
			if (!$this->data['total'])
			{
				return $this->complete();
			}
		}

		$threadFinder->where('thread_id', '>', $this->data['last']);

		$maxFetch = 1000;

		$threadIds = $threadFinder->pluckFrom('thread_id')->fetch($maxFetch)->toArray();
		if (!$threadIds)
		{
			return $this->complete();
		}

		$continue = count($threadIds) < $maxFetch ? false : true;

		foreach ($threadIds AS $threadId)
		{
			$this->data['count']++;
			$this->data['last'] = $threadId;

			$thread = $this->app->find(Thread::class, $threadId);
			if (!$thread)
			{
				continue;
			}

			$thread->discussion_type = $newDefaultType;
			$thread->saveIfChanged();

			if ($maxRunTime && microtime(true) - $s > $maxRunTime)
			{
				$continue = true;
				break;
			}
		}

		return $continue ? $this->resume() : $this->complete();
	}

	public function getStatusMessage()
	{
		$actionPhrase = \XF::phrase('changing_thread_types');
		return sprintf(
			'%s... (%s/%s)',
			$actionPhrase,
			\XF::language()->numberFormat($this->data['count']),
			\XF::language()->numberFormat($this->data['total'])
		);
	}

	public function canCancel()
	{
		return false;
	}

	public function canTriggerByChoice()
	{
		return false;
	}
}
