<?php
/**
 * @package         Tassos Code Snippets
 * @version         1.0.1-RC2 Free
 *
 * @author          Tassos Marinos <info@tassos.gr>
 * @link            https://www.tassos.gr
 * @copyright       Copyright © 2026 Tassos Marinos All Rights Reserved
 * @license         GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
 */

namespace Tassos\CodeSnippets\System\Extension;

defined('_JEXEC') or die;

use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\Event\SubscriberInterface;
use Joomla\CMS\Component\ComponentHelper;
use Tassos\CodeSnippets\Administrator\Location\LocationManager;
use Tassos\CodeSnippets\Administrator\Helper\SnippetsHelper;

/**
 * Tassos Code Snippets System Plugin
 * 
 * Responsible for:
 * - Loading the Tassos Framework
 * - Initializing the LocationManager after dispatch
 * 
 * The actual injection is handled by individual Location classes
 * that register themselves for the appropriate Joomla events.
 */
class TassosCodeSnippets extends CMSPlugin implements SubscriberInterface
{
    /**
     * Application instance
     *
     * @var \Joomla\CMS\Application\CMSApplication
     */
    protected $app;

    /**
     * Returns an array of events this subscriber will listen to.
     *
     * @return array
     */
    public static function getSubscribedEvents(): array
    {
        return [
            'onAfterRoute'     => 'onAfterRoute',
            'onContentPrepare' => 'onReplaceShortcodes',
            'onAfterRender'    => 'onReplaceShortcodes',
        ];
    }

    /**
     * Initialize all locations after route
     * 
     * We use onAfterRoute because it fires BEFORE the component is dispatched,
     * allowing us to register callbacks for ALL location events including:
     * 
     * - Content events (onContentAfterTitle, onContentBeforeDisplay, etc.)
     *   These fire DURING component dispatch when articles are rendered.
     * 
     * - Head events (onBeforeCompileHead)
     *   Fires after dispatch when the document head is compiled.
     * 
     * - Render events (onAfterRender)
     *   Fires after the page is fully rendered.
     * 
     * Using onAfterDispatch would NOT work for content locations because
     * by that point the article has already been rendered and content
     * events have already fired - we'd be too late to register.
     *
     * @return void
     */
    public function onAfterRoute(): void
    {
        // Only proceed if the component is enabled
        if (!ComponentHelper::isEnabled('com_tassoscodesnippets'))
        {
            return;
        }

        // Load Tassos Framework
        if (!@include_once(JPATH_PLUGINS . '/system/nrframework/autoload.php'))
        {
            return;
        }

        // Sanity check - if the LocationManager doesn't exist, we can't proceed
        if (!class_exists(LocationManager::class))
        {
            return;
        }

        // Initialize all locations
        LocationManager::initialize();
    }

    /**
     * Replace {tcs snippet.alias} shortcodes in article/module text (onContentPrepare)
     * and in the fully-rendered page body (onAfterRender).
     *
     * Both events are routed here. onContentPrepare processes each content item's
     * text before it is assembled into the page, while onAfterRender does a final
     * sweep of the complete HTML body to catch shortcodes inside buffer-injected
     * HTML snippets (site_body, site_header, etc.).
     *
     * @param   mixed  $event  The Joomla event object
     *
     * @return  void
     */
    public function onReplaceShortcodes($event = null): void
    {
        if (!$this->app->isClient('site'))
        {
            return;
        }

        $document = $this->app->getDocument();

        if (!$document || $document->getType() !== 'html')
        {
            return;
        }

        if ($event && $event->getName() === 'onContentPrepare')
        {
            $article = $event->getArgument('subject', $event->getArgument(1));

            if ($article && isset($article->text))
            {
                SnippetsHelper::replaceShortcodes($article->text);
            }

            return;
        }

        // onAfterRender: sweep the entire assembled page body
        $body = $this->app->getBody();
        SnippetsHelper::replaceShortcodes($body);
        $this->app->setBody($body);
    }
}