<?php
namespace LiteSpeed\CLI;

defined( 'WPINC' ) || exit;

use LiteSpeed\Core;
use LiteSpeed\Router;
use LiteSpeed\Admin_Display;
use WP_CLI;


/**
 * LiteSpeed Cache Purge Interface
 */
class Purge
{
	/**
	 * List all site domains and ids on the network.
	 *
	 * For use with the blog subcommand.
	 *
	 * ## EXAMPLES
	 *
	 *     # List all the site domains and ids in a table.
	 *     $ wp litespeed-purge network_list
	 */
	public function network_list( $args )
	{
		if ( ! is_multisite() ) {
			WP_CLI::error('This is not a multisite installation!');

			return;
		}
		$buf = WP_CLI::colorize("%CThe list of installs:%n\n");

		if ( version_compare($GLOBALS['wp_version'], '4.6', '<') ) {
			$sites = wp_get_sites();
			foreach ($sites as $site) {
				$buf .= WP_CLI::colorize('%Y' . $site['domain'] . $site['path'] . ':%n ID ' . $site['blog_id']) . "\n";
			}
		}
		else {
			$sites = get_sites();
			foreach ($sites as $site) {
				$buf .= WP_CLI::colorize('%Y' . $site->domain . $site->path . ':%n ID ' . $site->blog_id) . "\n";
			}
		}

		WP_CLI::line($buf);
	}

	/**
	 * Sends an ajax request to the site. Takes an action and the nonce string to perform.
	 *
	 * @since 1.0.14
	 */
	private function _send_request( $action, $extra = array() )
	{
		$data = array(
			Router::ACTION => $action,
			Router::NONCE => wp_create_nonce($action),
		);
		if ( ! empty( $extra ) ) {
			$data = array_merge( $data, $extra );
		}

		$url = admin_url( 'admin-ajax.php' );
		WP_CLI::debug( 'URL is ' . $url );

		$out = WP_CLI\Utils\http_request( 'GET', $url, $data );
		return $out;
	}

	/**
	 * Purges all cache entries for the blog (the entire network if multisite).
	 *
	 * ## EXAMPLES
	 *
	 *     # Purge Everything associated with the WordPress install.
	 *     $ wp litespeed-purge all
	 *
	 */
	public function all( $args )
	{
		if ( is_multisite() ) {
			$action = Core::ACTION_QS_PURGE_EMPTYCACHE;
		}
		else {
			$action = Core::ACTION_QS_PURGE_ALL;
		}

		$purge_ret = $this->_send_request( $action );

		if ( $purge_ret->success ) {
			WP_CLI::success(__('Purged All!', 'litespeed-cache'));
		}
		else {
			WP_CLI::error('Something went wrong! Got ' . $purge_ret->status_code);
		}
	}

	/**
	 * Purges all cache entries for the blog.
	 *
	 * ## OPTIONS
	 *
	 * <blogid>
	 * : The blog id to purge
	 *
	 * ## EXAMPLES
	 *
	 *     # In a multisite install, purge only the shop.example.com cache (stored as blog id 2).
	 *     $ wp litespeed-purge blog 2
	 *
	 */
	public function blog( $args )
	{
		if ( ! is_multisite() ) {
			WP_CLI::error('Not a multisite installation.');
			return;
		}
		$blogid = $args[0];
		if ( ! is_numeric($blogid) ) {
			$error = WP_CLI::colorize('%RError: invalid blog id entered.%n');
			WP_CLI::line($error);
			$this->network_list($args);
			return;
		}
		$site = get_blog_details($blogid);
		if ( $site === false ) {
			$error = WP_CLI::colorize('%RError: invalid blog id entered.%n');
			WP_CLI::line($error);
			$this->network_list($args);
			return;
		}
		switch_to_blog($blogid);

		$purge_ret = $this->_send_request(Core::ACTION_QS_PURGE_ALL);
		if ( $purge_ret->success ) {
			WP_CLI::success(__('Purged the blog!', 'litespeed-cache'));
		}
		else {
			WP_CLI::error('Something went wrong! Got ' . $purge_ret->status_code);
		}
	}

	/**
	 * Purges all cache tags related to a url.
	 *
	 * ## OPTIONS
	 *
	 * <url>
	 * : The url to purge.
	 *
	 * ## EXAMPLES
	 *
	 *     # Purge the front page.
	 *     $ wp litespeed-purge url https://mysite.com/
	 *
	 */
	public function url( $args )
	{
		$data = array(
			Router::ACTION => Core::ACTION_QS_PURGE,
		);
		$url = $args[0];
		$deconstructed = wp_parse_url($url);
		if ( empty($deconstructed) ) {
			WP_CLI::error('url passed in is invalid.');
			return;
		}

		if ( is_multisite() ) {
			if ( get_blog_id_from_url($deconstructed['host'], '/') === 0 ) {
				WP_CLI::error('Multisite url passed in is invalid.');
				return;
			}
		}
		else {
			$deconstructed_site = wp_parse_url( get_home_url() );
			if ( $deconstructed['host'] !== $deconstructed_site['host'] ) {
				WP_CLI::error('Single site url passed in is invalid.');
				return;
			}
		}

		WP_CLI::debug('url is ' . $url);

		$purge_ret = WP_CLI\Utils\http_request('GET', $url, $data);
		if ( $purge_ret->success ) {
			WP_CLI::success(__('Purged the url!', 'litespeed-cache'));
		}
		else {
			WP_CLI::error('Something went wrong! Got ' . $purge_ret->status_code);
		}
	}

	/**
	 * Helper function for purging by ids.
	 *
	 * @access private
	 * @since 1.0.15
	 * @param array $args The id list to parse.
	 * @param string $select The purge by kind
	 * @param function(int $id) $callback The callback function to check the id.
	 */
	private function _purgeby( $args, $select, $callback )
	{
		$filtered = array();
		foreach ($args as $val) {
			if ( ! ctype_digit($val) ) {
				WP_CLI::debug('[LSCACHE] Skip val, not a number. ' . $val);
				continue;
			}
			$term = $callback($val);
			if ( ! empty($term) ) {WP_CLI::line($term->name);
				$filtered[] = in_array( $callback, array( 'get_tag', 'get_category' ) ) ? $term->name : $val;
			}
			else {
				WP_CLI::debug('[LSCACHE] Skip val, not a valid term. ' . $val);
			}
		}

		if ( empty($filtered) ) {
			WP_CLI::error('Arguments must be integer ids.');
			return;
		}

		$str = implode(',', $filtered);

		$purge_titles = array(
			0 => 'Category',
			1 => 'Post ID',
			2 => 'Tag',
			3 => 'URL',
		);

		WP_CLI::line('Will purge the following: [' . $purge_titles[ $select ] . '] ' . $str);

		$data = array(
			Admin_Display::PURGEBYOPT_SELECT	=> $select,
			Admin_Display::PURGEBYOPT_LIST		=> $str,
		);

		$purge_ret = $this->_send_request( Core::ACTION_PURGE_BY, $data );
		if ( $purge_ret->success ) {
			WP_CLI::success(__('Purged!', 'litespeed-cache'));
		}
		else {
			WP_CLI::error('Something went wrong! Got ' . $purge_ret->status_code);
		}

	}

	/**
	 * Purges cache tags for a WordPress tag
	 *
	 * ## OPTIONS
	 *
	 * <ids>...
	 * : the Term IDs to purge.
	 *
	 * ## EXAMPLES
	 *
	 *     # Purge the tag ids 1, 3, and 5
	 *     $ wp litespeed-purge tag 1 3 5
	 *
	 */
	public function tag($args)
	{
		$this->_purgeby($args, Admin_Display::PURGEBY_TAG, 'get_tag');
	}

	/**
	 * Purges cache tags for a WordPress category
	 *
	 * ## OPTIONS
	 *
	 * <ids>...
	 * : the Term IDs to purge.
	 *
	 * ## EXAMPLES
	 *
	 *     # Purge the category ids 1, 3, and 5
	 *     $ wp litespeed-purge category 1 3 5
	 *
	 */
	public function category($args)
	{
		$this->_purgeby($args, Admin_Display::PURGEBY_CAT, 'get_category');
	}

	/**
	 * Purges cache tags for a WordPress Post/Product
	 *
	 * @alias product
	 *
	 * ## OPTIONS
	 *
	 * <ids>...
	 * : the Post IDs to purge.
	 *
	 * ## EXAMPLES
	 *
	 *     # Purge the post ids 1, 3, and 5
	 *     $ wp litespeed-purge post_id 1 3 5
	 *
	 */
	public function post_id( $args )
	{
		$this->_purgeby($args, Admin_Display::PURGEBY_PID, 'get_post');
	}

}
