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

use SabaiApps\Directories\Application;
use SabaiApps\Directories\Component\System\Tool\ITool;
use SabaiApps\Directories\Exception;

/**
 * ToolsHelper provides methods to retrieve and manage system tools from components.
 */
class ToolsHelper {

	private $_impls = array();

	/**
	 * Returns all available tools from components implementing System\ITools.
	 *
	 * @param Application $application
	 * @param bool        $useCache
	 * @return array
	 */
	public function help( Application $application, $useCache = true ) {
		if ( ! $useCache
			|| ( ! $tools = $application->getPlatform()->getCache( 'system_tools' ) )
		) {
			$tools = array();
			foreach ( $application->InstalledComponentsByInterface( 'System\ITools' ) as $component_name ) {
				if ( ! $application->isComponentLoaded( $component_name ) ) {
					continue;
				}

				foreach ( $application->getComponent( $component_name )->systemGetToolNames() as $tool_name ) {
					if ( ! $tool = $application->getComponent( $component_name )->systemGetTool( $tool_name ) ) {
						continue;
					}
					$tools[ $tool_name ] = array(
						'weight'    => $tool->systemToolInfo( 'weight' ),
						'component' => $component_name,
					);
				}
			}
			if ( ! empty( $tools ) ) {
				uasort(
					$tools,
					function ( $a, $b ) {
						return $a['weight'] < $b['weight'] ? -1 : 1;
					}
				);
				foreach ( array_keys( $tools ) as $tool_name ) {
					$tools[ $tool_name ] = $tools[ $tool_name ]['component'];
				}
			} else {
				$tools['system_reload']      = 'System';
				$tools['system_clear_cache'] = 'System';
			}
			$application->getPlatform()->setCache( $tools, 'system_tools' );
		}

		return $tools;
	}

	/**
	 * Returns the tool implementation object for a given tool name.
	 *
	 * @param Application $application
	 * @param string      $tool
	 * @param bool        $returnFalse
	 * @return object|false
	 * @throws Exception\UnexpectedValueException
	 */
	public function impl( Application $application, $tool, $returnFalse = false ) {
		if ( ! isset( $this->_impls[ $tool ] ) ) {
			if ( ( ! $tools = $this->help( $application ) )
				|| ! isset( $tools[ $tool ] )
				|| ! $application->isComponentLoaded( $tools[ $tool ] )
			) {
				if ( $returnFalse ) {
					return false;
				}
				throw new Exception\UnexpectedValueException( sprintf( 'Invalid tool: %s', $tool ) );
			}
			$this->_impls[ $tool ] = $application->getComponent( $tools[ $tool ] )->systemGetTool( $tool );
		}

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


	/**
	 * Changes the collation of system tables to the specified collation.
	 *
	 * @param Application $application
	 * @param string      $collation
	 */
	public function changeCollation( Application $application, $collation ) {
		$tables  = array(
			'directory_directory',
			'display_display',
			'display_element',
			'entity_bundle',
			'entity_field',
			'entity_field_booking_info',
			'entity_field_calendar_slot',
			'entity_field_boolean',
			'entity_field_choice',
			'entity_field_color',
			'entity_field_date',
			'entity_field_entity_content_count',
			'entity_field_entity_featured',
			'entity_field_entity_parent',
			'entity_field_entity_reference',
			'entity_field_entity_terms',
			'entity_field_frontendsubmit_guest',
			'entity_field_location_address',
			'entity_field_name',
			'entity_field_number',
			'entity_field_payment_plan',
			'entity_field_paymentgateway_discount',
			'entity_field_paymentgateway_order',
			'entity_field_paymentgateway_plan',
			'entity_field_paymentgateway_subscription',
			'entity_field_price',
			'entity_field_range',
			'entity_field_review_rating',
			'entity_field_string',
			'entity_field_text',
			'entity_field_time',
			'entity_field_user_post_count',
			'entity_field_video',
			'entity_field_voting_vote',
			'entity_field_wp_file',
			'entity_fieldconfig',
			'notification_notification',
			'system_component',
			'system_route',
			'view_filter',
			'view_view',
			'voting_vote',
		);
		$prefix  = $application->getDB()->getResourcePrefix();
		$charset = in_array( $collation, array( 'utf8_general_ci', 'utf8_unicode_ci' ) ) ? 'utf8' : 'utf8mb4';
		foreach ( $application->Filter( 'system_collate_tables', $tables ) as $table_name ) {
			$sql = sprintf(
				'ALTER TABLE %s%s CONVERT TO CHARACTER SET %s COLLATE %s;',
				$prefix,
				$table_name,
				$charset,
				$collation
			);
			try {
				$application->getDB()->exec( $sql );
			} catch ( \Exception $e ) {
				$application->logError( $e->getMessage() );
			}
		}
	}

	public function button( Application $application, $toolName, array $options = array() ) {
		if ( $toolName instanceof ITool ) {
			$tool     = $toolName;
			$toolName = (string) $tool;
		} else {
			if ( ! $tool = $application->System_Tools_impl( $toolName, true ) ) {
				return;
			}
			if ( ! $tool->systemToolSupports() ) {
				return;
			}
		}

		$tool_info  = $tool->systemToolInfo();
		$url_params = array( 'tool' => $toolName );
		if ( ! empty( $tool_info['redirect'] )
			&& isset( $options['redirect'] )
			&& strlen( $options['redirect'] )
		) {
			$url_params['redirect'] = $options['redirect'];
		}
		return $application->LinkTo(
			isset( $tool_info['btn_label'] ) ? $tool_info['btn_label'] : $tool_info['label'],
			$application->Url( '/_drts/system/tool_with_progress', $url_params ),
			array(
				'btn'       => true,
				'container' => 'modal',
				'modalSize' => 'xl',
			),
			array( 'class' => DRTS_BS_PREFIX . 'btn ' . DRTS_BS_PREFIX . 'btn-outline-secondary' )
		);
	}
}
