<?php
namespace SabaiApps\Directories\Component\Captcha\Helper;

use SabaiApps\Directories\Application;
use SabaiApps\Directories\Component\Captcha\Api\IApi;
use SabaiApps\Directories\Exception;

class ApisHelper {

	private $_impls        = array();
	private static $_count = 0;

	/**
	 * @param Application $application
	 * @param bool        $useCache
	 * @return array
	 */
	public function help( Application $application, $useCache = true ) {
		if ( ! $useCache
			|| ( ! $apis = $application->getPlatform()->getCache( 'captcha_apis' ) )
		) {
			$apis = $weights = array();
			foreach ( $application->InstalledComponentsByInterface( 'Captcha\IApis' ) as $component_name ) {
				if ( ! $application->isComponentLoaded( $component_name ) ) {
					continue;
				}

				foreach ( $application->getComponent( $component_name )->captchaGetApiNames() as $api_name ) {
					if ( ! $api = $application->getComponent( $component_name )->captchaGetApi( $api_name ) ) {
						continue;
					}

					$apis[ $api_name ] = array(
						'component' => $component_name,
						'weight'    => $api->captchaApiInfo( 'weight' ),
					);
				}
			}
			uasort(
				$apis,
				function ( $a, $b ) {
					return $a['weight'] < $b['weight'] ? -1 : 1;
				}
			);
			foreach ( array_keys( $apis ) as $api_name ) {
				$apis[ $api_name ] = $apis[ $api_name ]['component'];
			}
			$application->getPlatform()->setCache( $apis, 'captcha_apis' );
		}

		return $apis;
	}

	/**
	 * @param Application $application
	 * @param string      $apiName
	 * @param bool        $returnFalse
	 * @return false|IApi
	 * @throws Exception\UnexpectedValueException
	 */
	public function impl( Application $application, $apiName, $returnFalse = false ) {
		if ( ! isset( $this->_impls[ $apiName ] ) ) {
			if ( ( ! $apis = $application->Captcha_Apis() )
				|| ! isset( $apis[ $apiName ] )
				|| ! $application->isComponentLoaded( $apis[ $apiName ] )
			) {
				if ( $returnFalse ) {
					return false;
				}
				throw new Exception\UnexpectedValueException( sprintf( 'Invalid captcha API: %s', $apiName ) );
			}
			$this->_impls[ $apiName ] = $application->getComponent( $apis[ $apiName ] )->captchaGetApi( $apiName );
		}

		return $this->_impls[ $apiName ];
	}

	/**
	 * @param Application $application
	 * @param string      $name
	 * @param string      $trigger
	 * @param string|null $apiName
	 * @return array|null
	 */
	public function form( Application $application, $name, $trigger = null, $apiName = null ) {
		if ( ! isset( $apiName ) ) {
			$apiName = $application->getComponent( 'Captcha' )->getConfig( 'api' );
		}

		if ( empty( $apiName ) ) {
			return;
		}

		try {
			$api = $this->impl( $application, $apiName );
		} catch ( Exception\UnexpectedValueException $e ) {
			$application->logError( $e );
			return null;
		}
		if ( ! $settings = $application->getComponent( 'Captcha' )->getConfig( 'api_settings', $apiName ) ) {
			$settings = array();
		}
		return $api->captchaApiForm( $settings, isset( $name ) ? $name : ++self::$_count, $trigger );
	}
}
