<?php

namespace IconPress\Dashboard;

use Ink\Notices\UserNotice;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}


add_action( 'iconpress/pages/integrations', [ 'IconPress\\Dashboard\\Base', 'addOptionsSection' ] );
add_filter( 'pre_set_site_transient_update_plugins', array( 'IconPress\\Dashboard\\Base', 'checkPluginUpdates' ), 100 );

/**
 * Class Base
 * @package IconPress\Helpers
 *
 * Utility class providing methods to connect with api.iconpress.io
 */
class Base
{
	const API_URL = 'https://customers.iconpress.io/';
	const ACTIVATE_URL = 'https://customers.iconpress.io/activate-iconpress';
	const ACTION_CONNECT = '0x000';
	const ACTION_DISCONNECT = '0x001';
	const RESPONSE_SUCCESS = '0x002';
	const RESPONSE_ERROR = '0x003';

	/**
	 * The partial name of the option that will store the auth info
	 * @var string
	 */
	private static $_authInfoOptionName = '_dash_auth_info';


	/**
	 * Add the IP Dash section in the IconPress > Integrations page
	 */
	public static function addOptionsSection()
	{
		$activated = self::isConnected();
		?>
		<div class="iconpress-pageSection ip-dashboardSection">
			<h2><?php _e( 'Activate IconPress', 'iconpress' ) ?></h2>
			<div class="ip-row ip-row--gutter35">
				<div class="ip-col-6">

					<?php
					if ( $activated ) { ?>
						<h3><?php _e( 'What\'s next?', 'iconpress' ); ?></h3>
						<ul class="ip-u-list">
							<li><?php _e( 'Connect IconFinder (<a href="#activate-iconfinder">the section below this one</a>) to gain access to tens of thousands of icons;', 'iconpress' ); ?></li>
							<li><?php echo sprintf( __( '<a href="%s">Upload</a> your own SVG icons.', 'iconpress' ), admin_url( 'admin.php?page=' . \IconPress\Base::PLUGIN_SLUG . '_upload' ) ); ?></li>
							<li><?php _e( 'use IconPress\'s page builder elements to insert your icons into your website\'s pages.', 'iconpress' ); ?></li>
						</ul>
						<?php
					}

					// DEACTIVATED
					else {
						?>

						<p class=" u-mb-25"><?php _e( 'To enjoy IconPress\'s full experience we strongly recommend to activate it with our customer dashboard.', 'iconpress' ); ?></p>

						<h3><?php _e( 'Why should you activate IconPress?', 'iconpress' ); ?></h3>
						<ul class="ip-goPro-featureList">
							<li><?php echo IconPress__getSvgIcon( [ 'id' => 'iconpress-icon-check', 'style' => 'opacity:.3' ] ); ?><?php echo sprintf( __( 'Access to tens of thousand of icons (in all sorts of colors and shapes) from <a href="%s">IconFinder</a>.', 'iconpress' ), 'https://www.iconfinder.com/?ref=iconpress' ); ?></li>
							<li><?php echo IconPress__getSvgIcon( [ 'id' => 'iconpress-icon-check', 'style' => 'opacity:.3' ] ); ?><?php _e( 'Upload your own icons.', 'iconpress' ); ?></li>
							<li><?php echo IconPress__getSvgIcon( [ 'id' => 'iconpress-icon-check', 'style' => 'opacity:.3' ] ); ?><?php _e( 'Edit Icon\'s code', 'iconpress' ); ?></li>
							<li><?php echo IconPress__getSvgIcon( [ 'id' => 'iconpress-icon-check', 'style' => 'opacity:.3' ] ); ?><?php _e( 'Download Icons', 'iconpress' ); ?></li>
							<li><?php echo IconPress__getSvgIcon( [ 'id' => 'iconpress-icon-check', 'style' => 'opacity:.3' ] ); ?><?php _e( 'and so much more to come!', 'iconpress' ); ?></li>
						</ul>

					<?php } ?>

				</div>
				<div class="ip-col-6 ip-col--leftSeparator">

					<?php

					// ACTIVATED
					if ( $activated ) {

						echo '<p class="u-mb-25">' . __( 'Congratulations! Your IconPress plugin is activated.', 'iconpress' ) . '</p>';

						echo '<ul class="ip-u-list">';

						$info = self::getAuthInfo();
						echo '<li>' . __( 'Your API Key:', 'iconpress' ) . ' <strong>' . esc_html( $info['api_key'] ) . '</strong></li>';

						$checkStatusUrl = add_query_arg( [
							'page' => \IconPress\Base::PLUGIN_SLUG . '_integrations',
							'iconpress_status_check' => true
						], admin_url( 'admin.php' ) );
						$checkStatusUrl = wp_nonce_url( $checkStatusUrl, \IconPress\Base::NONCE_ACTION, \IconPress\Base::NONCE_NAME );
						echo '<li><a href="' . esc_url( $checkStatusUrl ) . '" id="js-ipdash-check-status-button">' . __( 'Check status', 'iconpress' ) . '</a></li>';

						//#! Prevent unwanted hacking requests.
						//#! If the unlink domain action is needed, it can only be performed from the Dashboard, not from here.
						echo '<li><a href="' . esc_url( self::API_URL ) . '" target="_blank" title="' . __( 'Opens in a new tab/window', 'iconpress' ) . '"id="js-ipdash-button-disconnect">' . __( 'Deactivate', 'iconpress' ) . '</a></li>';

						echo '<li><a href="' . esc_url( self::API_URL ) . '" target="_blank" title="' . __( 'Will open in a new window/tab', 'iconpress' ) . '"
						   >' . __( 'Access IconPress customer dashboard', 'iconpress' ) . '</a></li>';

						echo '</ul>';
					}

					// NOT CONNECTED
					else {
						$c = add_query_arg( [ 'page' => \IconPress\Base::PLUGIN_SLUG . '_integrations' ], admin_url( 'admin.php' ) );
						$url = sprintf( self::ACTIVATE_URL . '?site_url=%s&client=%s&version=%s', $c, 'IconPress', ICONPRESS_VERSION );
						?>
						<h3><?php _e( 'How to activate?', 'iconpress' ) ?></h3>

						<ul class="ip-u-list">
							<li><?php _e( 'Click the Activate Now button below;', 'iconpress' ); ?></li>
							<li>
								<?php
								echo sprintf(
									__( 'Register or Login with your <a href="%s" target="%s">Envato Account</a> onto our <a href="%s" target="%s">Customer Dashboard</a> so we can identify your IconPress license and generate a custom API Key;', 'iconpress' ),
									'https://account.envato.com/',
									'_blank',
									self::API_URL,
									'_blank'
								); ?></li>
							<li><?php _e( 'After the key is generated into the dashboard, select a key from the licenses list and click the Activate button to return back to your website;', 'iconpress' ); ?></li>
						</ul>

						<a href="<?php echo esc_url( $url ); ?>" class="ip-btn ip-btn--lined ip-btn--blue" id="js-ipdash-connect-button"><?php _e( 'ACTIVATE NOW', 'iconpress' ) ?></a>
						<?php
					}
					?>

				</div>
			</div>
		</div>
		<?php
	}

	/**
	 * Retrieve the full name of the option storing the dash auth info
	 * @return string
	 */
	public static function getAuthInfoOptionName()
	{
		return \IconPress\Base::PLUGIN_SLUG . self::$_authInfoOptionName;
	}

	public static function saveAuthInfo( $data = [] )
	{
		$info = array_merge( self::getAuthInfo(), $data );
		update_option( self::getAuthInfoOptionName(), $info );
	}

	public static function getAuthInfo()
	{
		if ( defined( 'ICONPRESS_DASH_API_KEY' ) && ICONPRESS_DASH_API_KEY != '' ) {
			update_option( self::getAuthInfoOptionName(), [ 'connected' => true, 'api_key' => ICONPRESS_DASH_API_KEY ] );
		}
		return get_option( self::getAuthInfoOptionName(), [] );
	}

	public static function deleteAuthInfo()
	{
		delete_option( self::getAuthInfoOptionName() );
	}

	/**
	 * Check to see whether or not this domain has been linked with an API Key
	 * @return bool
	 */
	public static function isConnected()
	{
		$info = self::getAuthInfo();
		return ( isset( $info['connected'] ) && $info['connected'] && isset( $info['api_key'] ) && ! empty( $info['api_key'] ) );
	}

	/**
	 * Internal method to remove the auth data.
	 * This will NOT disconnect this domain. For this to actually happen you will have to login to api.iconpress.io dashboard and disconnect this domain from there.
	 */
	public static function __disconnect()
	{
		self::saveAuthInfo( [ 'connected' => false, 'api_key' => '' ] );
	}

	public static function filterRequestTimeout( $timeout = 5 )
	{
		return 20;
	}

	public static function filterRequestUserAgent( $userAgent = '' )
	{
		return 'IconPress v' . ICONPRESS_VERSION . ';WordPress v' . get_bloginfo( 'version' ) . ';' . get_bloginfo( 'url' );
	}

	public static function __addRequestFilters()
	{
		add_filter( 'http_request_timeout', [ '\\IconPress\\Dashboard\\Base', 'filterRequestTimeout' ], 90000 );
		add_filter( 'http_headers_useragent', [ '\\IconPress\\Dashboard\\Base', 'filterRequestUserAgent' ], 90000 );
	}

	public static function __removeRequestFilters()
	{
		remove_filter( 'http_request_timeout', [ '\\IconPress\\Dashboard\\Base', 'filterRequestTimeout' ], 90000 );
		remove_filter( 'http_headers_useragent', [ '\\IconPress\\Dashboard\\Base', 'filterRequestUserAgent' ], 90000 );
	}

	/**
	 * Helper method to check if the domain is linked.
	 * @return array|string Array on error, string otherwise
	 */
	private static function __helperCheckConnectionStatus()
	{
		self::__addRequestFilters();

		$authInfo = self::getAuthInfo();
		$apiKey = ( isset( $authInfo['api_key'] ) ? $authInfo['api_key'] : '' );

		if ( defined( 'ICONPRESS_DASH_API_KEY' ) ) {
			$apiKey = ICONPRESS_DASH_API_KEY;
			if ( empty( $apiKey ) ) {
				self::__disconnect();
				return self::RESPONSE_ERROR;
			}
		}
		elseif ( ! self::isConnected() && ! empty( $apiKey ) ) {
			self::__disconnect();
			return self::RESPONSE_ERROR;
		}

		$url = sprintf( self::API_URL . '?site_url=%s&action=%s&api_key=%s'
			, get_bloginfo( 'url' )
			, 'status'
			, $apiKey
		);
		$request = wp_remote_get( $url, [
			'timeout' => apply_filters( 'http_request_timeout', 5 ),
			'sslverify' => false,
			'user-agent' => apply_filters( 'http_headers_useragent', 'WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ) )
		] );

		self::__removeRequestFilters();

		//#! Validate response
		if ( is_wp_error( $request ) ) {
			return [ 'error' => $request->get_error_message() ];
		}
		$response = wp_remote_retrieve_body( $request );

		if ( empty( $response ) ) {
			return [ 'error' => __( 'No response from server.', 'iconpress' ) ];
		}
		$response = json_decode( $response, true );
		if ( is_scalar( $response ) && ! is_array( $response ) ) {
			return [ 'error' => __( 'Invalid response from server.', 'iconpress' ) ];
		}
		if ( isset( $response['error'] ) ) {
			return [ 'error' => $response['error'] ];
		}
		if ( isset( $response['status'] ) ) {
			if ( (bool)$response['status'] == true ) {
				return self::RESPONSE_SUCCESS;
			}
			return self::RESPONSE_ERROR;
		}
		return [ 'error' => __( 'Invalid response from server.', 'iconpress' ) ];
	}

	/**
	 * Check the connection status with api.iconpress.io
	 * Caches the result for 4h
	 * Access url: /admin.php?page=iconpress_integrations&nonce....
	 * @hooked to "admin_init"
	 */
	public static function checkStatus()
	{
		//#! Verify nonce
		$nonceName = \IconPress\Base::NONCE_NAME;
		$nonceAction = \IconPress\Base::NONCE_ACTION;
		if ( ! isset( $_REQUEST[$nonceName] ) || ! wp_verify_nonce( $_REQUEST[$nonceName], $nonceAction ) ) {
			return;
		}

		//#! Ensure the request is coming from the integrations page
		if ( ! isset( $_REQUEST['page'] ) || ( \IconPress\Base::PLUGIN_SLUG . '_integrations' != $_REQUEST['page'] ) ) {
			return;
		}

		if ( ! isset( $_REQUEST['iconpress_status_check'] ) ) {
			return;
		}

		//#! Check to see if there is an api key
		$authInfo = self::getAuthInfo();
		if ( empty( $authInfo['api_key'] ) ) {
			//#! Invalid call - You can't check for status without an api key
			return;
		}

		//#! Check status
		$status = self::__helperCheckConnectionStatus();

		if ( isset( $status['error'] ) ) {
			UserNotice::add( '<strong>[IconPress API]</strong> ' . sprintf( __( 'Status check: %s', 'iconpress' ), $status['error'] ), UserNotice::TYPE_ERROR, false );
			self::saveAuthInfo( [ 'connected' => false ] );
		}
		elseif ( $status == self::RESPONSE_ERROR ) {
			do_action( 'iconpress/dashboard/not-connected' );
			UserNotice::add( '<strong>[IconPress API]</strong> ' . __( 'Status check: Not connected', 'iconpress' ), UserNotice::TYPE_WARNING, false );
		}
		else {
			UserNotice::add( '<strong>[IconPress API]</strong> ' . __( 'Status check: Connected', 'iconpress' ), UserNotice::TYPE_SUCCESS, false );
		}

		$returnUrl = add_query_arg( [ 'page' => \IconPress\Base::PLUGIN_SLUG . '_integrations' ], admin_url( 'admin.php' ) );
		self::saveAuthInfo( [ 'connected' => ( $status == self::RESPONSE_SUCCESS ) ] );
		if ( ! headers_sent() ) {
			wp_redirect( $returnUrl );
			exit;
		}
	}

	/**
	 * Checks the url to see if this is a response from api.iconpress.io to a connect/link domain request
	 * @hooked to "admin_init"
	 */
	public static function checkApiResponse()
	{
		if ( isset( $_REQUEST['registered'] ) && ( 'success' == $_REQUEST['registered'] ) ) {
			if ( ! isset( $_REQUEST['api_key'] ) || empty( $_REQUEST['api_key'] ) ) {
				UserNotice::add( '<strong>[IconPress API]</strong> ' . __( 'Link Domain: Invalid request. Missing api key', 'iconpress' ), UserNotice::TYPE_ERROR, false );
				return;
			}

			self::saveAuthInfo( [
				'connected' => true,
				'api_key' => sanitize_text_field( $_REQUEST['api_key'] )
			] );

			//#! Redirect, to integrations page
			$returnUrl = add_query_arg( [ 'page' => \IconPress\Base::PLUGIN_SLUG . '_integrations' ], admin_url( 'admin.php' ) );
			wp_redirect( $returnUrl );
			exit;
		}
	}

	/**
	 * Update the plugins list to include the Envato plugins that require update. Triggered by the
	 * pre_set_site_transient_update_plugins filter.
	 *
	 * @param $plugins
	 * @return mixed
	 */
	public static function checkPluginUpdates( $plugins )
	{
		if ( empty( $plugins ) || ! isset( $plugins->checked ) ) {
			return $plugins; // No plugins
		}
		$wpPlugins = $plugins->checked;
		if ( ! is_array( $wpPlugins ) || empty( $wpPlugins ) ) {
			return $plugins; // No plugins
		}

		$authInfo = self::getAuthInfo();
		$apiKey = ( isset( $authInfo['api_key'] ) ? $authInfo['api_key'] : '' );

		if ( defined( 'ICONPRESS_DASH_API_KEY' ) ) {
			$apiKey = ICONPRESS_DASH_API_KEY;
			if ( empty( $apiKey ) ) {
				self::__disconnect();
				return $plugins;
			}
		}
		elseif ( ! self::isConnected() && ! empty( $apiKey ) ) {
			self::__disconnect();
			return $plugins;
		}

		self::__addRequestFilters();

		$request = wp_remote_get( self::API_URL . 'wp-json/iconpress/v1/get_plugin_info' );

		self::__removeRequestFilters();

		//#! Validate response
		if ( is_wp_error( $request ) ) {
			return $plugins;
		}
		$response = wp_remote_retrieve_body( $request );

		if ( empty( $response ) ) {
			return $plugins;
		}
		$response = json_decode( $response, true );
		if ( is_scalar( $response ) && ! is_array( $response ) ) {
			return $plugins;
		}
		if ( isset( $response['error'] ) ) {
			return $plugins;
		}

		$envatoPlugin = [
			'version' => 0,
			'item_id' => 22369178,
		];

		//#! If we couldn't retrieve the remote version, the're is no need to go any further
		if ( isset($response['version']) && !empty( $response['version'] ) ) {
			$envatoPlugin = array_merge($envatoPlugin, $response);
		}
		else {
			return $plugins;
		}

		$envatoPlugin = (object)$envatoPlugin;

		//#! Get the path to the plugins directory
		$pluginsDir = \Ink\Framework::getInstance( 'iconpress' )->getConfig( 'ink-content-dir' ) . 'plugins/';

		//#! Loop over plugins and compare to see if we have an update
		$plugins = (array)$plugins;
		// Loop over the plugins and see which needs update
		foreach ( $wpPlugins as $path => $version ) {
			$pluginData = get_plugin_data( $pluginsDir . $path );
			$wpPluginName = isset( $pluginData['Name'] ) ? $pluginData['Name'] : '';
			$wpPluginVersion = isset( $pluginData['Version'] ) ? $pluginData['Version'] : null;

			if ( empty( $wpPluginName ) || is_null( $wpPluginVersion ) ) {
				continue;
			}

			// Check plugin in Envato plugins
			// We have a match
			if ( isset( $envatoPlugin->plugin_name ) && $envatoPlugin->plugin_name == $wpPluginName ) {
				// Check plugin to see if it needs to be updated
				$v = isset( $envatoPlugin->version ) ? $envatoPlugin->version : null;
				if ( ! is_null( $v ) ) {
					// Needs update - prepare entry
					if ( version_compare( $v, $wpPluginVersion, '>' ) ) {
						// Get the update zip file
						$update_zip = self::__getPluginDownloadUrl( $envatoPlugin->item_id );
						if ( ! is_string( $update_zip ) ) {
							break; // No need to go any further
						}
						if ( ! isset( $pluginData['PluginURI'] ) || empty( $pluginData['PluginURI'] ) ) {
							continue;
						}
						// Add plugin to WordPress' list
						$plugins['response'][$path] = (object)array(
							'id' => $envatoPlugin->item_id,
							'slug' => str_replace( ' ', '-', trim( $envatoPlugin->plugin_name ) ),
							'plugin' => $path,
							'new_version' => $v,
							'upgrade_notice' => null,
							'url' => $pluginData['PluginURI'],
							'package' => $update_zip
						);
					}
				}
			}
		}

		return (object)$plugins;
	}

	/**
	 * Retrieve the download URL for the specified item id from Envato API
	 * @param $itemID
	 * @return bool|string String on success
	 */
	private static function __getPluginDownloadUrl( $itemID )
	{
		$authInfo = self::getAuthInfo();
		$apiKey = ( isset( $authInfo['api_key'] ) ? $authInfo['api_key'] : '' );

		if ( defined( 'ICONPRESS_DASH_API_KEY' ) ) {
			$apiKey = ICONPRESS_DASH_API_KEY;
			if ( empty( $apiKey ) ) {
				return false;
			}
		}
		elseif ( ! self::isConnected() && ! empty( $apiKey ) ) {
			return false;
		}

		$url = sprintf( self::API_URL . '?site_url=%s&action=%s&api_key=%s&item_id=%d'
			, get_bloginfo( 'url' )
			, 'get_plugin_download_url'
			, $apiKey
			, $itemID
		);
		$request = wp_remote_get( $url, [
			'timeout' => apply_filters( 'http_request_timeout', 5 ),
			'sslverify' => false,
			'user-agent' => apply_filters( 'http_headers_useragent', 'WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ) )
		] );

		self::__removeRequestFilters();

		//#! Validate response
		if ( is_wp_error( $request ) ) {
			return false;
		}
		$response = wp_remote_retrieve_body( $request );

		if ( empty( $response ) ) {
			return false;
		}
		$response = json_decode( $response, true );
		if ( is_scalar( $response ) && ! is_array( $response ) ) {
			return false;
		}
		if ( isset( $response['error'] ) ) {
			return false;
		}
		if ( isset( $response['download_url'] ) && ! empty( $response['download_url'] ) ) {
			return $response['download_url'];
		}
		return false;
	}
}
