<?php

/**
 * @package SimplePortal
 *
 * @author SimplePortal Team
 * @copyright 2015-2026 SimplePortal Team
 * @license BSD 3-clause
 * @version 2.0.0
 */

use BBC\ParserWrapper;
use ElkArte\Database\QueryInterface;
use ElkArte\Helper\Util;
use ElkArte\MessageTopicIcons;

/**
 * Advanced Recent Post / Topic block, shows the most recent posts or topics on the forum
 *
 * How to add a custom block to SP?  Filename and class name are vital for
 * proper discovery !!! Here filename is RecentEx.block.php and the class must be RecentExBlock
 *
 * @param array $parameters
 *        'boards' => list of boards to get posts from,
 *        'limit' => number of topics to show
 *          'firstLast' => show text from first or last post of topic
 *        'type' => Where to display body text (off, on hover, in the block)
 *        'length' => length of body text to show
 * @param int $id - not used in this block
 * @param bool $return_parameters if true returns the configuration options for the block
 */
class RecentExBlock extends SPAbstractBlock
{
	/**
	 * Constructor, used to define block parameters
	 *
	 * @param QueryInterface|null $db
	 */
	public function __construct($db = null)
	{
		global $txt;

		// Block Options text strings, used when setting up the block.
		// a full addon could add a txt file and use load language here for localization
		// or be lazy like this ;)  Again, string naming is vital.
		$txt['sp_param_RecentEx_boards'] = 'Boards';
		$txt['sp_param_RecentEx_limit'] = 'Number of items to show';
		$txt['sp_param_RecentEx_firstLast'] = 'Show the topic text from';
		$txt['sp_param_RecentEx_firstLast_options'] = 'First Post|Last Post';
		$txt['sp_param_RecentEx_type'] = 'Show post text';
		$txt['sp_param_RecentEx_type_options'] = 'None|On Hover|In Block';
		$txt['sp_param_RecentEx_length'] = 'Length of post text to show, 0 for all';
		$txt['sp_param_RecentEx_refresh_value'] = 'Refresh value in seconds, 0 or blank to disable.';

		$this->block_parameters = [
			'boards' => 'boards',
			'limit' => 'int',
			'length' => 'int',
			'firstLast' => 'select',
			'type' => 'select',
			'refresh_value' => 'int'
		];

		self::blockName();
		self::blockDescription();
		parent::__construct($db);
	}

	/**
	 * Sets the name of the block
	 */
	public static function blockName()
	{
		global $txt;

		$txt['sp_function_RecentEx_label'] = 'Recent Extended';
	}

	/**
	 * Sets the description of the block
	 */
	public static function blockDescription()
	{
		global $txt;

		$txt['sp_function_RecentEx_desc'] = 'Enhanced recent topic block with icons and preview';
	}

	/**
	 * Initializes a block for use.
	 *
	 * - Called from portal.subs as part of the sportal_load_blocks process
	 *
	 * @param array $parameters
	 * @param int $id
	 */
	public function setup($parameters, $id)
	{
		global $settings, $scripturl, $user_info, $modSettings;

		// Clean the parameters
		$boards = !empty($parameters['boards']) ? explode('|', $parameters['boards']) : null;
		$limit = !empty($parameters['limit']) ? (int)$parameters['limit'] : 10;
		$show_body = $parameters['type'] !== '0';
		$preview_char = isset($parameters['length']) ? (int)$parameters['length'] : 128;
		$preview_last = $parameters['firstLast'] === '1';

		$this->data['items'] = [];
		$this->data['show_body'] = $show_body;
		$this->data['show_body_where'] = $parameters['type'];

		// Only certain boards?
		if (is_array($boards) || (int)$boards === $boards)
		{
			$boards = is_array($boards) ? $boards : [$boards];
		}
		elseif ($boards !== null)
		{
			$boards = [];
		}

		// Topic icons
		$icon_sources = new MessageTopicIcons(!empty($modSettings['messageIconChecks_enable']), $settings['theme_dir']);

		// No previews at all
		if ($show_body === false)
		{
			$preview_bodies = '';
		}
		// 0 means everything, seems logical
		elseif (empty($preview_char))
		{
			$preview_bodies = ', ml.body AS last_body, mf.body AS first_body';
		}
		// A SUBSTRING with some buffer
		else
		{
			$preview_bodies = ', SUBSTRING(ml.body, 1, ' . ($preview_char + 256) . ') AS last_body, SUBSTRING(mf.body, 1, ' . ($preview_char + 256) . ') AS first_body';
		}

		// Find all the posts in distinct topics.  Newer ones will have higher IDs.
		$request = $this->_db->query('substring', '
			SELECT
				mf.subject,
				ml.id_msg, ml.id_topic, ml.id_member, ml.poster_time,
				b.id_board, b.name AS bName,
				t.num_replies, t.num_views, t.id_first_msg, t.id_last_msg,
				COALESCE(mem.real_name, ml.poster_name) AS poster_name, ' . ($user_info['is_guest'] ? '1 AS is_read, 0 AS new_from' : '
				COALESCE(lt.id_msg, lmr.id_msg, 0) >= ml.id_msg_modified AS is_read,
				COALESCE(lt.id_msg, lmr.id_msg, -1) + 1 AS new_from') . ', mf.smileys_enabled, mf.icon, mg.online_color' .
			$preview_bodies . '
			FROM {db_prefix}topics AS t
				INNER JOIN {db_prefix}messages AS mf ON (mf.id_msg = t.id_first_msg)
				INNER JOIN {db_prefix}messages AS ml ON (ml.id_msg = t.id_last_msg)
				LEFT JOIN {db_prefix}boards AS b ON (b.id_board = mf.id_board)
				LEFT JOIN {db_prefix}members AS mem ON (mem.id_member = ml.id_member)' . (!$user_info['is_guest'] ? '
				LEFT JOIN {db_prefix}log_topics AS lt ON (lt.id_topic = t.id_topic AND lt.id_member = {int:current_member})
				LEFT JOIN {db_prefix}log_mark_read AS lmr ON (lmr.id_board = b.id_board AND lmr.id_member = {int:current_member})' : '') . '
				LEFT JOIN {db_prefix}membergroups AS mg ON (mg.id_group = mem.id_group)
			WHERE t.id_last_msg >= {int:likely_max_msg}
				AND b.id_board = t.id_board' . ($boards === null ? '' : '
				AND b.id_board IN ({array_int:include_boards})') . '
				AND {query_wanna_see_board}' . ($modSettings['postmod_active'] ? '
				AND t.approved = {int:is_approved}
				AND ml.approved = {int:is_approved}' : '') . '
			ORDER BY t.id_last_msg DESC
			LIMIT {int:limit}',
			[
				'current_member' => $user_info['id'],
				'include_boards' => $boards,
				'limit' => $limit,
				'is_approved' => 1,
				'likely_max_msg' => $modSettings['maxMsgID'] - 25 * min($limit, 5),
				'preview_char' => $preview_char,
			]
		);
		$parser = ParserWrapper::instance();
		while ($row = $request->fetch_assoc())
		{
			// Shorten and censor the body as needed
			$row['body'] = '';
			if ($show_body)
			{
				$row['body'] = strtr($parser->parseMessage($preview_last ? $row['last_body'] : $row['first_body'], true), ['&nbsp;' => ' ']);
				if (!empty($preview_char))
				{
					$row['body'] = Util::shorten_html($row['body'], $preview_char, true);
				}
			}

			// Censorship is the new normal.
			censor($row['subject']);
			censor($row['body']);

			// Build the array.
			$this->data['items'][] = [
				'board' => [
					'id' => $row['id_board'],
					'name' => $row['bName'],
					'href' => $scripturl . '?board=' . $row['id_board'] . '.0',
					'link' => '<a href="' . getUrl('board', ['board' => $row['id_board'], 'name' => $row['bName']]) . '">' . $row['bName'] . '</a>',
				],
				'topic' => $row['id_topic'],
				'poster' => [
					'id' => $row['id_member'],
					'name' => $row['poster_name'],
					'href' => empty($row['id_member']) ? '' : $scripturl . '?action=profile;u=' . $row['id_member'],
					'link' => empty($row['id_member']) ? $row['poster_name'] : ('<a href="' . getUrl('profile', ['action' => 'profile', 'u' => $row['id_member']]) . '">' . $row['poster_name'] . '</a>'),
				],
				'subject' => $row['subject'],
				'short_subject' => Util::shorten_text($row['subject'], 25),
				'preview' => $row['body'],
				'time' => standardTime($row['poster_time']),
				'timestamp' => forum_time(true, $row['poster_time']),
				'href' => $scripturl . '?topic=' . $row['id_topic'] . '.msg' . $row['id_msg'] . ';topicseen#new',
				'link' => '<a href="' . getUrl('action', ['topic' => $row['id_topic'] . '.msg' . $row['id_msg'], 'hash' => '#new']) . '">' . $row['subject'] . '</a>',
				'new' => !empty($row['is_read']),
				'new_from' => $row['new_from'],
				'icon' => $icon_sources->getIconName($row['icon']),
				'icon_url' => $icon_sources->getIconURL($row['icon']),
				'views' => $row['num_views'],
				'replies' => $row['num_replies'],
			];
		}
		$request->free_result();

		// Colorization
		$this->_colorids();

		// Enabling auto refresh?
		if (!empty($parameters['refresh_value']) && !$user_info['is_guest'])
		{
			$this->refresh = ['sa' => 'recent', 'class' => '.sp_recent', 'id' => $id, 'refresh_value' => $parameters['refresh_value']];
			$this->auto_refresh();
		}

		// Off you go
		$this->setTemplate('template_sp_recent_ex');
	}

	/**
	 * Provide the color profile id's
	 */
	private function _colorids()
	{
		global $color_profile;

		$color_ids = [];
		foreach ($this->data['items'] as $item)
		{
			if (!empty($item['poster']) && isset($item['poster']['id']))
			{
				$color_ids[] = $item['poster']['id'];
			}
		}

		if (!empty($color_ids) && sp_loadColors($color_ids) !== false)
		{
			foreach ($this->data['items'] as $k => $p)
			{
				if (!empty($color_profile[$p['poster']['id']]['link']))
				{
					$this->data['items'][$k]['poster']['link'] = $color_profile[$p['poster']['id']]['link'];
				}
			}
		}
	}
}

/**
 * Main template for this block
 *
 * @param array $data
 */
function template_sp_recent_ex($data)
{
	global $scripturl, $txt;

	if (empty($data['items']))
	{
		echo '
		', $txt['error_sp_no_posts_found'];

		return;
	}

	echo '
<style>
	.recent_ex_tr {display: flex; padding:0 8px;border-bottom:1px dashed #6394BD;align-items:center;}
	.recent_ex_tr1 {display: table-cell;border-bottom:1px dashed #6394BD;width:100%;padding:8px 0;}
	.recent_ex_tr2 {font-weight: bold;}
</style>
<div>';

	foreach ($data['items'] as $post)
	{
		$title = $data['show_body'] && $data['show_body_where'] === '1' ? Util::htmlspecialchars($post['preview']) : '';
		echo '
	<div style="display: flex">
		<div class="recent_ex_tr centericon">
			<img src="', $post['icon_url'], '" alt="', $post['icon'], '" />
		</div>
		<div class="recent_ex_tr1">
			', $post['new'] ? '' : '<a href="' . $scripturl . '?topic=' . $post['topic'] . '.msg' . $post['new_from'] . ';topicseen#new" rel="nofollow"><span class="new_posts"> ' . $txt['new'] . '</span></a>', '
			<a class="recent_ex_tr2" href="', $post['href'], '" title="', $title, '">', $post['subject'], '</a>
			<div class="smalltext">
				', $txt['by'], ' ', $post['poster']['link'], ' ', $txt['in'], ' ', $post['board']['link'], '
				</br />
				', $post['time'], ' | ', $txt['views'], ': ', $post['views'], ' | ', $txt['replies'], ': ', $post['replies'], '
			</div>';

		if ($data['show_body'] && $data['show_body_where'] === '2')
		{
			echo '
			<div class="post">
			', $post['preview'], '
			</div>';
		}

		echo '
		</div>
	</div>';
	}

	echo '
</div>';

	// Preview message body?
	if ($data['show_body'] && $data['show_body_where'] === '1')
	{
		theme()->addInlineJavascript('
	$(document).ready(function () {
		$(".recent_ex_tr2").SiteTooltip({
			hoverIntent: {sensitivity: 10, interval: 150, timeout: 50}
		});
	});', true);
	}
}
