<?php

class OTGS_Installer_Upgrade_Response {

	/**
	 * @var array
	 */
	private $_plugins;

	/**
	 * @var OTGS_Installer_Plugin_Finder
	 */
	private $plugin_finder;

	/**
	 * @var OTGS_Installer_Repositories
	 */
	private $repositories;

	/**
	 * @var OTGS_Installer_Source_Factory
	 */
	private $source_factory;

	/**
	 * @var OTGS_Installer_Package_Product_Finder
	 */
	private $product_finder;

	public function __construct( OTGS_Installer_Plugin_Finder $plugin_finder, OTGS_Installer_Repositories $repositories, OTGS_Installer_Source_Factory $source_factory, OTGS_Installer_Package_Product_Finder $product_finder ) {
		$this->plugin_finder  = $plugin_finder;
		$this->repositories   = $repositories;
		$this->source_factory = $source_factory;
		$this->product_finder = $product_finder;
	}

	public function add_hooks() {
		if ( defined( 'DOING_AJAX' ) && isset( $_POST['action'] ) && 'installer_download_plugin' === $_POST['action'] ) {
			add_filter( 'site_transient_update_plugins', array( $this, 'modify_upgrade_response' ) );
		}

		add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'modify_upgrade_response' ) );
	}

	private function plugins() {
	  	if ( null === $this->_plugins ) {
			$this->_plugins = $this->plugin_finder->get_all();
		}

		return $this->_plugins;
	}

	/**
	 * @param stdClass|null $update_plugins
	 * @return mixed
	 */
	public function modify_upgrade_response( $update_plugins ) {
		if ( isset( $update_plugins ) && is_object( $update_plugins ) ) {
			foreach ( $this->plugins() as $plugin ) {
				$repository   = $this->repositories->get( $plugin->get_repo() );
				$subscription = $repository->get_subscription();

				$response = (object) [
					'id'            => $plugin->get_id(),
					'slug'          => $plugin->get_slug(),
					'plugin'        => $plugin->get_id(),
					'new_version'   => $plugin->get_version(),
				];

				if ( $this->should_skip_upgrade_process( $plugin, $update_plugins, $repository ) ) {
					$update_plugins->no_update[ $plugin->get_id() ] = $response;
					continue;
				}

				$response->upgrade_notice = '';
				$response->url            = $plugin->get_url();
				$response->tested         = $plugin->get_tested();

				if ( $subscription->get_site_key() ) {
					$response->package = $this->append_site_key_to_download_url(
						$plugin->get_url(),
						$subscription->get_site_key(),
						$repository->get_id(),
						WP_Installer()->get_installer_site_url()
					);
				}

				$response = apply_filters( 'otgs_installer_upgrade_check_response', $response, $plugin->get_name(), $repository->get_id() );

				$update_plugins->checked[ $plugin->get_id() ]  = $plugin->get_installed_version();
				$update_plugins->response[ $plugin->get_id() ] = $response;
			}
		}

		return $update_plugins;
	}

	private function should_skip_upgrade_process( OTGS_Installer_Plugin $plugin, $update_plugins, OTGS_Installer_Repository $repository ) {
		$has_wp_org_update = isset( $update_plugins->response[ $plugin->get_id() ] );
		$subscription      = $repository->get_subscription();
		$needs_upgrade     = $plugin->get_installed_version() && version_compare( $plugin->get_version(), $plugin->get_installed_version(), '>' ) || ! empty( $_POST['reset_to_channel'] );

		if ( ! $needs_upgrade ) {
			return true;
		}

		if ( ! $subscription || ! $subscription->is_valid() ) {
			return true;
		}

		if ( isset( $update_plugins->response[ $plugin->get_id() ] ) ) {
			return true;
		}

		if ( $this->is_plugin_registered_on_external_repo( $plugin ) ) {
			return true;
		}

		$product = $this->product_finder->get_product_in_repository_by_subscription( $repository );

		if ( ! $product || ! $product->is_plugin_registered( $plugin->get_slug() ) ) {
			return true;
		}

		if ( $subscription && $this->should_fallback_under_wp_org_repo( $plugin, $subscription->get_site_key() ) && $has_wp_org_update ) {
			return true;
		}

		return false;
	}

	private function is_plugin_registered_on_external_repo( OTGS_Installer_Plugin $plugin ) {
		$repository = $this->repositories->get( $plugin->get_external_repo() );

		if ( $repository ) {
			$product = $this->product_finder->get_product_in_repository_by_subscription( $repository );

			if ( $product && $plugin->get_external_repo() && $product->is_plugin_registered( $plugin->get_slug() ) ) {
				return true;
			}
		}

		return false;
	}

	private function append_site_key_to_download_url( $url, $key, $repository_id, $site_url ) {

		$url_params['site_key'] = $key;
		$url_params['site_url'] = $site_url;

		$url = add_query_arg( $url_params, $url );

		if ( 'wpml' === $repository_id ) {
			$url = add_query_arg( array(
				'using_icl'    => function_exists( 'wpml_site_uses_icl' ) && wpml_site_uses_icl(),
				'wpml_version' => defined( 'ICL_SITEPRESS_VERSION' ) ? ICL_SITEPRESS_VERSION : ''
			), $url );
		}

		return $url;
	}

	private function get_extra_url_parameters( $source ) {
		$parameters = array();

		if ( $source ) {
			foreach ( $source as $key => $val ) {
				$parameters[ $key ] = $val;
			}
		}

		$parameters['installer_version'] = WP_INSTALLER_VERSION;
		$parameters['theme']             = wp_get_theme()->get( 'Name' );
		$parameters['site_name']         = get_bloginfo( 'name' );

		return $parameters;
	}

	private function should_fallback_under_wp_org_repo( OTGS_Installer_Plugin $plugin, $site_key ) {
		return ( $plugin->is_free_on_wporg() || $plugin->has_fallback_on_wporg() && $plugin->has_fallback_on_wporg() && ! $site_key ) && $plugin->get_channel() === WP_Installer_Channels::CHANNEL_PRODUCTION;
	}
}
