<?php

namespace MediaWiki\Extension\Math\Rest;

use MediaWiki\Extension\Math\MathWikibaseConnector;
use MediaWiki\Extension\Math\MathWikibaseInfo;
use MediaWiki\Html\Html;
use MediaWiki\Languages\LanguageFactory;
use MediaWiki\Languages\LanguageNameUtils;
use MediaWiki\Rest\Response;
use MediaWiki\Rest\SimpleHandler;
use MediaWiki\Title\Title;
use MediaWiki\Title\TitleFactory;
use Wikimedia\ParamValidator\ParamValidator;

class Popup extends SimpleHandler {

	/** @var MathWikibaseConnector */
	private $wikibase;

	/** @var LanguageFactory */
	private $languageFactory;

	/** @var LanguageNameUtils */
	private $languageNameUtils;

	/** @var Title|null */
	private $specialPageTitle;

	/**
	 * @param MathWikibaseConnector $wikibase
	 * @param LanguageFactory $languageFactory
	 * @param LanguageNameUtils $languageNameUtils
	 * @param TitleFactory $titleFactory
	 */
	public function __construct(
		MathWikibaseConnector $wikibase,
		LanguageFactory $languageFactory,
		LanguageNameUtils $languageNameUtils,
		TitleFactory $titleFactory
	) {
		$this->wikibase = $wikibase;
		$this->languageFactory = $languageFactory;
		$this->languageNameUtils = $languageNameUtils;
		$this->specialPageTitle = $titleFactory->newFromText( 'Special:MathWikibase' );
	}

	public function run( int $qid ): Response {
		$uselang = $this->getRequest()->getHeaderLine( 'Accept-Language' );
		if ( $uselang === '' ) {
			$uselang = 'en';
		}
		$rf = $this->getResponseFactory();
		if ( $this->languageNameUtils->isValidCode( $uselang ) ) {
			$langObj = $this->languageFactory->getLanguage( $uselang );
		} else {
			return $rf->createHttpError( 400, [ 'message' => 'Invalid language code.' ] );
		}

		try {
			$info = $this->wikibase->fetchWikibaseFromId( "Q{$qid}", $uselang );
		} catch ( \InvalidArgumentException $exception ) {
			return $rf->createHttpError( 400, [ 'message' => $exception->getMessage() ] );
		}

		$html = $this->buildHTMLRepresentation( $info );

		$response = [
			'title' => $info->getLabel(),
			'contentmodel' => 'html',
			'pagelanguagedir' => $langObj->getDir(),
			'pagelanguage' => $langObj->getCode(),
			'pagelanguagehtmlcode' => $langObj->getHtmlCode(),
			'extract' => $html
		];

		if ( $this->specialPageTitle ) {
			$response = array_merge( $response, [
				'canonicalurl' => $this->specialPageTitle->getLocalURL( [ 'qid' => "Q{$qid}" ] ),
				'fullurl' => $this->specialPageTitle->getFullURL( [ 'qid' => "Q{$qid}" ] )
			] );
		}

		return $rf->createJson( $response );
	}

	/**
	 * Generates an HTML string from the given data.
	 * @param MathWikibaseInfo $info an info object generated by fetchWikibaseFromId
	 * @return string an HTML representation of the given info object
	 */
	private function buildHTMLRepresentation( MathWikibaseInfo $info ): string {
		$output =
			Html::openElement( "div",
				[ "style" =>
					"width: 100%; display: flex; flex-direction: column;
					align-items: flex-start; flex-wrap: wrap;" ] );
		$output .= Html::element( "span", [
			"style" => "font-weight: bold; text-transform: capitalize;"
		], $info->getLabel() );
		$output .= Html::element( "span", [ "style" => "font-size: small" ], " (" . $info->getDescription() . ")" );
		if ( $info->hasParts() ) {
			$output .= Html::rawElement( "div",
				[ "style" => "width: 100%; display: flex; justify-content: left; padding-top: 5px;" ],
				$info->generateSmallTableOfParts() );
		}
		$output .= Html::closeElement( "div" );

		return $output;
	}

	public function getParamSettings(): array {
		return [
			'qid' => [
				self::PARAM_SOURCE => 'path',
				ParamValidator::PARAM_TYPE => 'integer',
				ParamValidator::PARAM_REQUIRED => true
			]
		];
	}
}
