<?php
/*
** Copyright (C) 2021-2026 initMAX s.r.o.
**
** This program is free software: you can redistribute it and/or modify it under the terms of
** the GNU Affero General Public License as published by the Free Software Foundation, version 3.
**
** This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
** without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
** See the GNU Affero General Public License for more details.
**
** You should have received a copy of the GNU Affero General Public License along with this program.
** If not, see <https://www.gnu.org/licenses/>.
**/


namespace Modules\TetrisMAX;

use CController as CAction;
use Core\CModule as ModuleBase;

require_once version_compare(ZABBIX_VERSION, '6.2', '>=')
	? 'CWidgetConfig.6.2.php'
	: 'CWidgetConfig.6.0.php';

/**
 * Registration for Zabbix 6.0 / 6.2.
 *
 * Those two lines have no manifest that can declare a widget, no asset bundle
 * and no widget registry a module may extend - so this class does the three
 * jobs the manifest does on 6.4+: it registers the widget (through the
 * generated cooperative CWidgetConfig fork), it loads the client, and it loads
 * the stylesheets.
 *
 * ONE PRODUCT: every file it loads is GENERATED by build-edition.py from the
 * very sources the 6.4+ package ships. Nothing here is a hand-kept copy, which
 * is the only thing that stops the two trees drifting into two games.
 */
class Module extends ModuleBase {

	/** URL-relative base of the deployed legacy module directory. */
	public function assetDir(): string {
		return 'modules/'.basename(__DIR__);
	}

	/**
	 * @param CAction $action Action instance responsible for current request.
	 */
	public function onBeforeAction(CAction $action): void {
		if ($action->getAction() !== 'dashboard.view') {
			return;
		}

		// ONE CLIENT: these are the very files the 6.4+ tree ships, copied in
		// at build time from assets/js/ - the v1 tree keeps no client of its
		// own, because a fork is how a fix lands on one Zabbix line and not the
		// other.
		//
		// ORDER IS THIS LOOP'S JOB. Manifest-v1 has no asset bundle, so the
		// board and the pieces have to be defined before the widget shell that
		// builds them. Getting it wrong left the shell throwing
		// "GameBoard is not defined" with an empty tile and no error on screen.
		foreach (['class.gameboard.js', 'class.tetromino.js', 'class.widget.js'] as $script) {
			$file = __DIR__.'/public/js/'.$script;

			if (is_file($file)) {
				zbx_add_post_js(file_get_contents($file));
			}
		}

		// Manifest-v1 has no CSS bundle either. build-edition.py generates
		// these stylesheets from the same sources the 6.4+ manifest lists, so
		// loading every generated sheet keeps the board, the score panel and
		// the game-over card looking identical on 6.0/6.2 - down to the web
		// font, which a hand-kept copy famously loses by pointing at the wrong
		// directory.
		foreach (glob(__DIR__.'/public/css/*.css') ?: [] as $sheet) {
			$name = basename($sheet);
			$this->installCss($name, 'tetrismax-'.basename($name, '.css').'-css');
		}
	}

	/** Inject a generated legacy stylesheet into the page head. */
	private function installCss(string $file, string $element_id): void {
		$path = __DIR__.'/public/css/'.$file;

		if (!is_readable($path)) {
			return;
		}

		// The build leaves a PLACEHOLDER where the deployed directory goes:
		// 6.0/6.2 INLINE a module's stylesheet into the page, so a relative
		// url('../img/x.svg') would resolve against zabbix.php and every
		// sprite would 404. The real directory is only known here, because
		// package postinstall may deploy the tree outside /usr/share.
		$assets = $this->assetDir().'/public';
		$css = strtr((string) file_get_contents($path), [
			'%%MODULE_ASSETS%%' => $assets,
			'modules/tetrismax-legacy/public' => $assets,
			'modules/tetrismax/public' => $assets
		]);

		zbx_add_post_js(
			'if (document.getElementById('.json_encode($element_id).') === null) {'
			.'const style = document.createElement("style");'
			.'style.id = '.json_encode($element_id).';'
			.'style.textContent = '.json_encode($css).';'
			.'document.head.appendChild(style);'
			.'}'
		);
	}
}
