<?php
namespace Isekai\ChatComplete\Api;

use ApiBase;
use ApiMain;
use ApiModuleManager;
use Isekai\ChatComplete\Api\ChatCompleteBot\ApiReportUsage;
use Isekai\ChatComplete\Api\ChatCompleteBot\ApiUserInfo;
use MediaWiki\MediaWikiServices;
use Wikimedia\ParamValidator\ParamValidator;

class ApiChatCompleteBot extends ApiBase {
    public static $methodModules = [
        'reportusage' => [
            'class' => ApiReportUsage::class,
        ],
        'userinfo' => [
            'class' => ApiUserInfo::class,
        ],
    ];

    private $mModuleMgr;
    private $mParams;
    /**
     * @param ApiMain $main
     * @param string $action
     */
    public function __construct( ApiMain $main, $action )
    {
        parent::__construct($main, $action);

        $this->mModuleMgr = new ApiModuleManager(
            $this,
            MediaWikiServices::getInstance()->getObjectFactory()
        );

        // Allow custom modules to be added in LocalSettings.php
        $config = $this->getConfig();
        $this->mModuleMgr->addModules( self::$methodModules, 'method' );
    }

    /**
     * Overrides to return this instance's module manager.
     * @return ApiModuleManager
     */
    public function getModuleManager() {
        return $this->mModuleMgr;
    }

    public function execute() {
        $this->mParams = $this->extractRequestParams();

        $modules = [];
        $this->instantiateModules( $modules, 'method' );
        $this->getResult()->addValue(null, 'modules', array_keys($modules));

        foreach ( $modules as $module ) {
            $module->execute();
        }
    }

    /**
     * Create instances of all modules requested by the client
     * @param array &$modules To append instantiated modules to
     * @param string $param Parameter name to read modules from
     */
    private function instantiateModules( &$modules, $param ) {
        $wasPosted = $this->getRequest()->wasPosted();
        if ( isset( $this->mParams[$param] ) ) {
            foreach ( $this->mParams[$param] as $moduleName ) {
                $instance = $this->mModuleMgr->getModule( $moduleName, $param );
                if ( $instance === null ) {
                    ApiBase::dieDebug( __METHOD__, 'Error instantiating module' );
                }
                if ( !$wasPosted && $instance->mustBePosted() ) {
                    $this->dieWithErrorOrDebug( [ 'apierror-mustbeposted', $moduleName ] );
                }
                // Ignore duplicates. TODO 2.0: die()?
                if ( !array_key_exists( $moduleName, $modules ) ) {
                    $modules[$moduleName] = $instance;
                }
            }
        }
    }

    public function getAllowedParams( $flags = 0 ) {
        $result = [
            'method' => [
                ParamValidator::PARAM_ISMULTI => true,
                ParamValidator::PARAM_TYPE => 'submodule',
            ],
        ];

        return $result;
    }

    public function isInternal() {
		return true;
	}
}