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

use SabaiApps\Directories\Component\AbstractComponent;
use SabaiApps\Directories\Context;
use SabaiApps\Directories\Application;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

/**
 * SystemComponent provides API and UI for managing components, routes, logs, and tools.
 * Handles route registration, event dispatching, logging, and scheduled tasks.
 */
class SystemComponent extends AbstractComponent implements IAdminRouter, ITools, IScheduledActions {

	const VERSION = '2.0.6', PACKAGE = 'directories-pro';

	/**
	 * Returns a description of the component.
	 *
	 * @return string
	 */
	public static function description() {
		return 'Provides API and UI for managing components.';
	}

	/**
	 * Returns an array of variable directories required by the component.
	 *
	 * @return array
	 */
	public function hasVarDir() {
		$ret = array();
		if ( ! $this->_application->getPlatform()->getLogDir() ) {
			$ret[] = 'logs';
		}
		if ( ! $this->_application->getPlatform()->getTmpDir() ) {
			$ret[] = 'tmp';
		}
		return $ret;
	}

	/**
	 * Gets the log directory path.
	 *
	 * @return string
	 */
	public function getLogDir() {
		if ( ! empty( $this->_config['log_dir'] ) ) {
			return $this->_config['log_dir'];
		}

		return ( $dir = $this->_application->getPlatform()->getLogDir() ) ? $dir : $this->getVarDir( 'logs' );
	}

	/**
	 * Gets the temporary directory path.
	 *
	 * @return string
	 */
	public function getTmpDir() {
		return ( $dir = $this->_application->getPlatform()->getTmpDir() ) ? $dir : $this->getVarDir( 'tmp' );
	}

	public function isDebugEnabled() {
		return ! empty( $this->_config['log_debug'] ) || $this->_application->getPlatform()->isDebugEnabled();
	}

	/**
	 * Returns an array of admin routes provided by the component.
	 *
	 * @return array
	 */
	public function systemAdminRoutes() {
		return array(
			'/directories/settings'            => array(
				'controller'      => 'Settings',
				'access_callback' => true,
				'title_callback'  => true,
				'callback_path'   => 'settings',
				'type'            => Application::ROUTE_TAB,
				'weight'          => 98,
			),
			'/directories/system'              => array(
				'controller'      => 'System',
				'access_callback' => true,
				'title_callback'  => true,
				'callback_path'   => 'system',
				'type'            => Application::ROUTE_TAB,
				'weight'          => 99,
			),
			'/_drts/system/tool_with_progress' => array(
				'controller' => 'RunToolWithProgress',
			),
			'/_drts/system/progress'           => array(
				'controller' => 'Progress',
				'type'       => Application::ROUTE_CALLBACK,
			),
			'/_drts/system/log'                => array(
				'controller' => 'ViewLog',
				'type'       => Application::ROUTE_CALLBACK,
			),
			'/_drts/system/download'           => array(
				'controller' => 'Download',
				'type'       => Application::ROUTE_CALLBACK,
			),
		);
	}

	/**
	 * Handles access control for admin routes.
	 */
	public function systemOnAccessAdminRoute( Context $context, $path, $accessType, array &$route ) {
		switch ( $path ) {
			case 'settings':
			case 'system':
				if ( $accessType === Application::ROUTE_ACCESS_LINK ) {
					return $this->_application->getUser()->isAdministrator();
				}
				return true;
		}
	}

	/**
	 * Returns the title for an admin route.
	 */
	public function systemAdminRouteTitle( Context $context, $path, $titleType, array $route ) {
		switch ( $path ) {
			case 'settings':
				return __( 'Settings', 'directories-pro' );
			case 'system':
				return __( 'System', 'directories-pro' );
		}
	}

	/**
	 * Handles installation of main router interface for a component.
	 *
	 * @param AbstractComponent $component
	 */
	public function onSystemIMainRouterInstalled( AbstractComponent $component ) {
		$this->_onSystemIRouterInstalled( $component, false );
	}

	/**
	 * Handles installation of admin router interface for a component.
	 *
	 * @param AbstractComponent $component
	 */
	public function onSystemIAdminRouterInstalled( AbstractComponent $component ) {
		$this->_onSystemIRouterInstalled( $component, true );
	}

	/**
	 * Installs routes for a component.
	 *
	 * @param AbstractComponent $component
	 * @param bool              $admin
	 */
	private function _onSystemIRouterInstalled( AbstractComponent $component, $admin = false ) {
		if ( $admin ) {
			$this->_createRoutes( $component, $component->systemAdminRoutes(), true );
		} else {
			$this->_createRoutes( $component, $component->systemMainRoutes( false ) );
			foreach ( $this->_application->getPlatform()->getLanguages() as $lang ) {
				$this->_createRoutes( $component, $component->systemMainRoutes( $lang ), false, $lang );
			}
		}
	}

	/**
	 * Creates route entries in the database for a component.
	 *
	 * @param AbstractComponent $component
	 * @param array             $routes
	 * @param bool              $admin
	 * @param string            $lang
	 */
	private function _createRoutes( AbstractComponent $component, array $routes, $admin = false, $lang = '' ) {
		if ( empty( $routes ) ) {
			return;
		}

		$model      = $this->getModel();
		$root_paths = array();

		// Insert route data
		foreach ( $routes as $route_path => $route_data ) {
			$route_path = strtolower( rtrim( $route_path, '/' ) );
			if ( $lang !== '' && strpos( $route_path, '/_drts' ) === 0 ) {
				continue;
			}

			$route = $model->create( 'Route' );
			$route->markNew();
			$route->admin                = $admin;
			$route->controller           = (string) ( $route_data['controller'] ?? '' );
			$route->forward              = (string) ( $route_data['forward'] ?? '' );
			$route->component            = $component->getName();
			$route->controller_component = isset( $route_data['controller_component'] ) ? $route_data['controller_component'] : $component->getName();
			$route->type                 = isset( $route_data['type'] ) ? $route_data['type'] : Application::ROUTE_NORMAL;
			$route->path                 = $route_path;
			$route->format               = (array) ( $route_data['format'] ?? array() );
			$route->method               = (string) ( $route_data['method'] ?? '' );
			$route->access_callback      = ! empty( $route_data['access_callback'] ) ? 1 : 0;
			$route->title_callback       = ! empty( $route_data['title_callback'] ) ? 1 : 0;
			$route->callback_path        = isset( $route_data['callback_path'] ) ? $route_data['callback_path'] : $route_path;
			$route->callback_component   = isset( $route_data['callback_component'] ) ? $route_data['callback_component'] : $component->getName();
			$route->weight               = isset( $route_data['weight'] ) ? ( $route_data['weight'] > 99 ? 99 : $route_data['weight'] ) : 9;
			$route->depth                = substr_count( $route_path, '/' );
			$route->language             = $lang;
			$route->data                 = (array) ( $route_data['data'] ?? array() );
			if ( ! isset( $route_data['priority'] ) ) {
				// Set lower priority if it is a child route of another plugin
				if ( 0 !== strpos( str_replace( '_', '', $route_path ), '/' . strtolower( $component->getName() ) ) ) {
					$route->priority = 3; // default is 5
				}
			} else {
				$route->priority = intval( $route_data['priority'] );
			}

			if ( $root_path = substr( $route_path, 0, strpos( $route_path, '/', 1 ) ) ) {
				$root_paths[ $root_path ] = $root_path;
			}
		}

		$model->commit();

		// Clear cached route data
		if ( ! empty( $root_paths ) ) {
			$lang = $this->_application->getPlatform()->getCurrentLanguage();
			foreach ( $root_paths as $root_path ) {
				$this->_application->getPlatform()->deleteCache( 'system_' . ( $admin ? 'route_admin' : 'route' ) . str_replace( '/', '_', $root_path ) . '_' . $lang );
			}
		}
	}

	/**
	 * Handles uninstallation of main router interface for a component.
	 *
	 * @param AbstractComponent $component
	 */
	public function onSystemIMainRouterUninstalled( AbstractComponent $component ) {
		$this->_onSystemIRouterUninstalled( $component, false );
	}

	/**
	 * Handles uninstallation of admin router interface for a component.
	 *
	 * @param AbstractComponent $component
	 */
	public function onSystemIAdminRouterUninstalled( AbstractComponent $component ) {
		$this->_onSystemIRouterUninstalled( $component, true );
	}

	/**
	 * Removes routes for a component from the database.
	 *
	 * @param AbstractComponent $component
	 * @param bool              $admin
	 */
	private function _onSystemIRouterUninstalled( AbstractComponent $component, $admin = false ) {
		$model    = $this->getModel();
		$criteria = $model->createCriteria( 'Route' )->admin_is( $admin )->component_is( $component->getName() );
		$model->getGateway( 'Route' )->deleteByCriteria( $criteria );
	}

	/**
	 * Reloads routes for a specific component.
	 *
	 * @param AbstractComponent $component
	 * @param bool              $admin
	 * @return $this
	 */
	public function reloadRoutes( AbstractComponent $component, $admin = false ) {
		$this->_onSystemIRouterUninstalled( $component, $admin );
		$this->_onSystemIRouterInstalled( $component, $admin );
		return $this;
	}

	/**
	 * Reloads all routes for all components.
	 *
	 * @param bool $mainOnly If true, reload only main routes.
	 * @return $this
	 */
	public function reloadAllRoutes( $mainOnly = false ) {
		$routes = $this->getModel( 'Route' );
		if ( $mainOnly ) {
			$routes->admin_is( 0 );
			$interfaces = array( 'System\IMainRouter' => 0 );
		} else {
			$interfaces = array(
				'System\IMainRouter'  => 0,
				'System\IAdminRouter' => 1,
			);
		}
		$routes->delete();
		foreach ( $interfaces as $interface => $is_admin ) {
			foreach ( $this->_application->InstalledComponentsByInterface( $interface ) as $component_name ) {
				if ( ! $this->_application->isComponentLoaded( $component_name ) ) {
					continue;
				}

				$this->_onSystemIRouterInstalled( $this->_application->getComponent( $component_name ), $is_admin );
			}
		}
		$this->_application->Action( 'system_all_routes_reloaded', array( $mainOnly ) );
		return $this;
	}

	/**
	 * Handles the layout rendering event to load default assets and initialize JS.
	 *
	 * @param Context $context
	 * @param string  $content
	 * @param array   $vars
	 */
	public function onCoreResponseSendViewLayout( Context $context, &$content, &$vars ) {
		$this->_application->getPlatform()->loadDefaultAssets()
			->addJs( 'DRTS.init($("' . $context->getContainer() . '"));', true, -99 );
	}

	/**
	 * Handles the response completion event to save flash messages to session.
	 *
	 * @param Context $context
	 */
	public function onCoreResponseSendComplete( Context $context ) {
		// Save response messages to session if flashing is enabled
		if ( $context->isFlashEnabled() && ( $flash = $context->getFlash() ) ) {
			$this->_application->getPlatform()->setSessionVar( 'system_flash', $flash );
		}
	}

	/**
	 * Gets main routes for a given root path and language.
	 *
	 * @param string      $rootPath
	 * @param string|null $lang
	 * @return array
	 */
	public function getMainRoutes( $rootPath = '/', $lang = null ) {
		if ( ! isset( $lang ) ) {
			if ( ! $lang = $this->_application->getPlatform()->getCurrentLanguage() ) {
				$lang = '';
			}
		}
		return $this->_getRoutes( $rootPath, false, $lang );
	}

	/**
	 * Gets admin routes for a given root path.
	 *
	 * @param string $rootPath
	 * @return array
	 */
	public function getAdminRoutes( $rootPath = '/' ) {
		return $this->_getRoutes( $rootPath, true );
	}

	/**
	 * Internal method to fetch routes from the database and cache them.
	 *
	 * @param string $rootPath
	 * @param bool   $admin
	 * @param string $lang
	 * @return array
	 */
	private function _getRoutes( $rootPath, $admin = false, $lang = '' ) {
		$root_path = rtrim( $rootPath, '/' );

		if ( $lang !== '' && strpos( $root_path, '/_drts' ) === 0 ) {
			$lang = '';
		}

		// Check if already cached
		$cache_id = 'system_' . ( $admin ? 'route_admin' : 'route' ) . str_replace( '/', '_', $root_path ) . '_' . $lang;
		if ( $cache = $this->_application->getPlatform()->getCache( $cache_id ) ) {
			return $cache;
		}

		$ret    = array();
		$routes = $this->getModel( 'Route' )
			->admin_is( $admin )
			->path_startsWith( $root_path )
			->language_is( $lang )
			// fetch routes with lower priority first so that the ones with higher priority will overwrite them
			->fetch( 0, 0, 'priority', 'ASC' );
		if ( $routes->count() ) {
			$root_path_dir = dirname( $root_path );
			foreach ( $routes as $route ) {
				if ( ! $this->_application->isComponentLoaded( $route->component ) ) {
					continue;
				}

				// Initialize route data
				// Any child route data already defined?
				$child_routes                  = ! empty( $ret[ $route->path ]['routes'] ) ? $ret[ $route->path ]['routes'] : array();
				$ret[ $route->path ]           = $route->toArray();
				$ret[ $route->path ]['routes'] = $child_routes;

				$current_path = $route->path;
				while ( $root_path_dir !== $parent_path = dirname( $current_path ) ) {
					$current_base = substr( $current_path, strlen( $parent_path ) + 1 ); // remove the parent path part

					if ( ! isset( $ret[ $current_path ]['path'] ) ) {
						// Check whether format is defined if dynamic route
						$format = array();
						if ( 0 === strpos( $current_base, ':' ) && isset( $ret[ $route->path ]['format'][ $current_base ] ) ) {
							$format = $ret[ $route->path ]['format'][ $current_base ];
							unset( $ret[ $route->path ]['format'][ $current_base ] );
						}
						$ret[ $current_path ]['path']      = $current_path;
						$ret[ $current_path ]['component'] = $route->component;
						$ret[ $current_path ]['type']      = Application::ROUTE_NORMAL;
						$ret[ $current_path ]['format']    = ! empty( $format ) ? array( $current_base => $format ) : array();
					}
					if ( ! isset( $ret[ $parent_path ]['component'] ) ) {
						$ret[ $parent_path ]['component'] = $route->component;
					}
					$ret[ $parent_path ]['routes'][ $current_base ] = $current_path;

					$current_path = $parent_path;
				}
			}
		}

		// Allow components to modify routes
		$ret = $this->_application->Filter( 'system_routes', $ret, array( $rootPath, $admin, $lang ) );
		// Cache routes
		$this->_application->getPlatform()->setCache( $ret, $cache_id );

		return $ret;
	}

	/**
	 * Handles the event when a component is installed.
	 *
	 * @param Model\Component $componentEntity
	 */
	public function onSystemComponentInstalled( Model\Component $componentEntity ) {
		$component = $this->_application->getComponent( $componentEntity->name );

		$this->_invokeComponentEvents( $component, 'installed', 'install_success' );
	}

	/**
	 * Handles the event when a component is uninstalled.
	 *
	 * @param Model\Component $componentEntity
	 */
	public function onSystemComponentUninstalled( Model\Component $componentEntity ) {
		$component = $this->_application->getComponent( $componentEntity->name );

		$this->_invokeComponentEvents( $component, 'uninstalled', 'uninstall_success' );
	}

	/**
	 * Handles the event when a component is upgraded.
	 *
	 * @param Model\Component $componentEntity
	 * @param string          $previousVersion
	 */
	public function onSystemComponentUpgraded( Model\Component $componentEntity, $previousVersion ) {
		$component = $this->_application->getComponent( $componentEntity->name );

		$this->_invokeComponentEvents( $component, 'upgraded', 'upgrade_success', array( $previousVersion ) );

		if ( $componentEntity->name === $this->_name
			&& version_compare( $previousVersion, self::VERSION, '<' )
		) {
			$this->_application->System_ScheduledActions_schedule( false );
		}
	}

	/**
	 * Invokes component events for installed, uninstalled, or upgraded actions.
	 *
	 * @param AbstractComponent $component
	 * @param string            $event
	 * @param string            $event2
	 * @param array             $args
	 */
	private function _invokeComponentEvents( AbstractComponent $component, $event, $event2, array $args = array() ) {
		$event_component_name = strtolower( $component->getName() );
		$args                 = array_merge( array( $component ), $args );
		$this->_application->Action( $event_component_name . '_' . $event, $args );

		// Invoke first set of events for each interface implemented by the component
		if ( $interfaces = class_implements( $component, false ) ) { // get interfaces implemented by the plugin
			// Remove component namespace part
			$prefix = 'SabaiApps\\Directories\\Component\\';
			foreach ( array_keys( $interfaces ) as $k ) {
				if ( strpos( $interfaces[ $k ], $prefix ) === 0 ) {
					$_interface       = trim( substr( $interfaces[ $k ], strlen( $prefix ) ), '\\' );
					$interfaces[ $k ] = $_interface;
				} else {
					unset( $interfaces[ $k ] );
				}
			}
			$interfaces = array_flip( $interfaces );
		} else {
			$interfaces = array();
		}
		if ( is_callable( array( $component, 'interfaces' ) )
			&& ( $_interfaces = call_user_func( array( $component, 'interfaces' ) ) ) // check for extra interfaces implemented
		) {
			$interfaces += array_flip( $_interfaces );
		}
		if ( ! empty( $interfaces ) ) {
			// Dispatch event for each interface
			foreach ( array_keys( $interfaces ) as $interface ) {
				$action = str_replace( '\\', '_', strtolower( $interface ) ) . '_' . $event;
				$this->_application->Action( $action, $args );
			}
		}

		$this->_application->Action( $action = $event_component_name . $event2, $args );

		// Invoke second set of events for each interface implemented by the component
		if ( ! empty( $interfaces ) ) {
			// Dispatch event for each interface
			foreach ( array_keys( $interfaces ) as $interface ) {
				$action = str_replace( '\\', '_', strtolower( $interface ) ) . '_' . $event2;
				$this->_application->Action( $action, $args );
			}
		}
	}

	/**
	 * Handles the event when widgets are installed for a component.
	 *
	 * @param AbstractComponent $component
	 */
	public function onSystemIWidgetsInstalled( AbstractComponent $component ) {
		$this->_application->getPlatform()->deleteCache( 'system_widgets' );
	}

	/**
	 * Handles the event when widgets are uninstalled for a component.
	 *
	 * @param AbstractComponent $component
	 */
	public function onSystemIWidgetsUninstalled( AbstractComponent $component ) {
		$this->_application->getPlatform()->deleteCache( 'system_widgets' );
	}

	/**
	 * Handles the event when widgets are upgraded for a component.
	 *
	 * @param AbstractComponent $component
	 */
	public function onSystemIWidgetsUpgraded( AbstractComponent $component ) {
		$this->_application->getPlatform()->deleteCache( 'system_widgets' );
	}

	/**
	 * Handles the event when core components are loaded.
	 * Sets up logging and displays flash messages from session.
	 */
	public function onCoreComponentsLoaded() {
		if ( $logger = $this->_application->getLogger() ) {
			if ( empty( $this->_config['disable_error_log'] ) ) {
				// Add a log handler to write error logs
				$logger->pushHandler( new StreamHandler( $this->getLogDir() . '/drts_error.log', Logger::ERROR ) );
			}
			if ( $this->isDebugEnabled() ) {
				// Add a log handler to write logs with debug level or up
				$logger->pushHandler( new StreamHandler( $this->getLogDir() . '/drts_debug.log', Logger::DEBUG ) );
			}
		}

		// Show messages saved in session during the previous request as flash messages
		if ( $flash = $this->_application->getPlatform()->getSessionVar( 'system_flash' ) ) {
			$this->_application->getPlatform()->addFlash( $flash )
				->deleteSessionVar( 'system_flash' );
		}
	}

	public function onCorePlatformWordPressInit() {
		$this->_application->System_ScheduledActions_init();
	}

	/**
	 * Handles WordPress admin initialization for core platform.
	 * Checks for component updates and reloads components if needed.
	 */
	public function onCorePlatformWordPressAdminInit() {
		if ( ! $this->_application->getUser()->isAdministrator() ) {
			return;
		}

		if ( false === $updates = $this->_application->getPlatform()->getCache( 'system_component_updates' ) ) {
			$updates              = array();
			$installed_components = $this->_application->InstalledComponents();
			$local_components     = $this->_application->LocalComponents();
			foreach ( $installed_components as $component_name => $installed_component ) {
				if ( isset( $local_components[ $component_name ] )
					&& version_compare( $installed_component['version'], $local_components[ $component_name ]['version'], '<' )
				) {
					$updates[] = $component_name;
				}
			}
			$this->_application->getPlatform()->setCache( $updates, 'system_component_updates' );
		}
		if ( ! empty( $updates )
			&& $this->_application->getPlatform()->isAdmin()
		) {
			$flash = $errors = array();
			$this->_application->callHelper( 'System_Component_reload', array( &$errors ) );
			if ( ! empty( $errors ) ) {
				foreach ( $errors as $error ) {
					$flash[] = array(
						'msg'   => $error,
						'level' => 'danger',
					);
				}
			} else {
				$flash[] = array(
					'msg'   => sprintf( __( '%d component(s) have been updated.', 'directories-pro' ), count( $updates ) ),
					'level' => 'success',
				);
			}
			$this->_application->getPlatform()->addFlash( $flash );
		}
	}

	/**
	 * Adds log file information to the admin logs filter.
	 *
	 * @param array $logs
	 */
	public function onSystemAdminSystemLogsFilter( &$logs ) {
		$logs['error'] = array(
			'label'           => '<i class="fas fa-fw fa-triangle-exclamation ' . DRTS_BS_PREFIX . 'text-danger"></i> '
				. $this->_application->H( __( 'Error log', 'directories-pro' ) ),
			'label_no_escape' => true,
			'file'            => $this->getLogDir() . '/drts_error.log',
			'weight'          => 1,
		);
		$logs['debug'] = array(
			'label'           => '<i class="fas fa-fw fa-circle-info ' . DRTS_BS_PREFIX . 'text-info"></i> ' . $this->_application->H( __( 'Debug log', 'directories-pro' ) ),
			'label_no_escape' => true,
			'file'            => $this->getLogDir() . '/drts_debug.log',
			'weight'          => 5,
			'days'            => 30,
		);
	}

	/**
	 * Returns an array of scheduled system actions.
	 *
	 * @return array
	 */
	public function systemScheduledActions() {
		return array(
			'system_clear_tmp'         => array(
				'title'       => __( 'Clear temporary files', 'directories-pro' ),
				'description' => __( 'Clears files in the temporary directory.', 'directories-pro' ),
				'recurrence'  => 'weekly',
				'args'        => array(),
				'priority'    => 15,
			),
			'system_clear_logs'        => array(
				'title'       => __( 'Clear log files', 'directories-pro' ),
				'description' => __( 'Deletes log files to free up disk space.', 'directories-pro' ),
				'recurrence'  => 'monthly',
				'args'        => array(),
				'priority'    => 15,
				'enabled'     => false,
			),
			'sysetm_reload_components' => array(
				'title'       => __( 'Reload components', 'directories-pro' ),
				'description' => __( 'Reloads all installed components to ensure they are up to date.', 'directories-pro' ),
				'recurrence'  => 'monthly',
				'args'        => array(),
				'priority'    => 15,
				'enabled'     => false,
			),
		);
	}

	/**
	 * Clears the temporary directory.
	 */
	public function onSystemClearTmp() {
		$files = new \RecursiveIteratorIterator(
			new \RecursiveDirectoryIterator( $this->getTmpDir(), \RecursiveDirectoryIterator::SKIP_DOTS ),
			\RecursiveIteratorIterator::CHILD_FIRST
		);
		foreach ( $files as $file ) {
			$func = ( $file->isDir() ? 'rmdir' : 'unlink' );
			$func( $file->getRealPath() );
		}
		$this->_application->logNotice( __( 'Cleared tmp directory', 'directories-pro' ) );
	}

	/**
	 * Clears log files.
	 */
	public function onSystemClearLogs() {
		$log_files = $this->_application->Filter( 'system_admin_system_logs', array() );
		foreach ( $log_files as $log ) {
			@unlink( $log['file'] );
		}
		$this->_application->logNotice( __( 'Cleared log files', 'directories-pro' ) );
	}

	/**
	 * Reloads all components.
	 */
	public function onSystemReloadComponents() {
		$this->_application->System_Component_reload();
	}

	/**
	 * Returns an array of available tool names.
	 *
	 * @return array
	 */
	public function systemGetToolNames() {
		return array(
			'system_reload',
			'system_clear_cache',
			'system_alter_collation',
			'system_clear_logs',
			'system_export_settings',
			'system_import_settings',
		);
	}

	/**
	 * Returns the tool object for the given tool name.
	 *
	 * @param string $name
	 * @return mixed
	 */
	public function systemGetTool( $name ) {
		switch ( $name ) {
			case 'system_reload':
				return new Tool\ReloadComponentsTool( $this->_application, $name );
			case 'system_clear_cache':
				return new Tool\ClearCacheTool( $this->_application, $name );
			case 'system_alter_collation':
				return new Tool\AlterCollationTool( $this->_application, $name );
			case 'system_clear_logs':
				return new Tool\ClearLogsTool( $this->_application, $name );
			case 'system_export_settings':
				return new Tool\ExportSettingsTool( $this->_application, $name );
			case 'system_import_settings':
				return new Tool\ImportSettingsTool( $this->_application, $name );
		}
	}

	/**
	 * Adds system settings fields to the admin settings form.
	 *
	 * @param array $form
	 */
	public function onDirectoryAdminSettingsFormFilter( &$form ) {
		// Moved from Directory to System component
		$this->onSystemAdminSettingsFormFilter( $form );
	}

	public function onSystemAdminSettingsFormFilter( &$form ) {
		$this->_application->callHelper( 'System_SettingsForm', array( $this->_name, $this->_config, &$form ) );
	}

	public function onSystemComponentConfigSaved( $componentName, $config ) {
		if ( $componentName !== $this->_name ) {
			return;
		}

		$this->_application->System_ScheduledActions_schedule();
	}

	/**
	 * Sets the uninstall remove data flag based on config.
	 *
	 * @param bool $bool
	 */
	public function onCoreUninstallRemoveDataFilter( &$bool ) {
		$bool = ! empty( $this->_config['uninstall_remove_data'] );
	}
}
