<?php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

/**
 * WPJobster update API.
 *
 * @author WPJobster
 * @version 1.0.3
 */

if ( ! class_exists( 'WPJ_Plugin_License' ) ) {
	class WPJ_Plugin_License extends \stdClass {
		private $file;
		private $license;
		private $item_name;
		private $item_id;
		private $version;
		private $author = 'WPJobster';
		private $api_url;
		private $short_slug;
		private $full_slug;
		private $textdomain;
		private $type;

		public  $sl_version = 'undefined';


		function __construct( $plugin_data ) {
			$this->file       = $plugin_data['file'];
			$this->item_name  = isset( $plugin_data['item_name'] ) ? $plugin_data['item_name'] : false;
			$this->item_id    = isset( $plugin_data['item_id'] ) ? $plugin_data['item_id'] : false;
			$this->version    = $plugin_data['version'];
			$this->license    = isset( $_POST['wpjobster_' . $this->short_slug . '_license_key'] ) ? $_POST['wpjobster_' . $this->short_slug . '_license_key'] : wpj_get_option( 'wpjobster_' . $this->short_slug . '_license_key' );
			$this->author     = $plugin_data['author'];
			$this->api_url    = is_null( $plugin_data['api_url'] ) ? $this->api_url : $plugin_data['api_url'];
			$this->short_slug = $plugin_data['short_slug'];
			$this->full_slug  = $plugin_data['full_slug'];
			$this->textdomain = isset( $plugin_data['textdomain'] ) ? $plugin_data['textdomain'] : $plugin_data['short_slug'];
			$this->type       = isset( $plugin_data['type'] ) ? $plugin_data['type'] : '';

			// Setup hooks
			$this->includes();
			$this->hooks();
		}


		private function includes() {
			if ( ! class_exists( 'EDD_SL_Plugin_Updater' ) ) {
				// load our custom updater
				include ( plugin_dir_path( __FILE__ ) . 'plugin-updater-class.php' );
			}
		}


		private function hooks() {

			// Register settings
			add_action( 'admin_init', array( $this, 'register_option') );

			// Activate license key on settings save
			add_action( 'admin_init', array( $this, 'activate_license' ) );

			// Deactivate license key
			add_action( 'admin_init', array( $this, 'deactivate_license' ) );

			// Initialize the updater
			add_action( 'admin_init', array( $this, 'updater' ), 0 );

			// Display errors
			add_action( 'admin_notices', array( $this, 'wpjobster_admin_notices' ) );

			// Display message in update notice
			add_action( 'in_plugin_update_message-' . plugin_basename( $this->file ), array( $this, 'plugin_row_license_missing' ), 10, 2 );

			// Display page
			add_action( 'wpjobster_display_' . $this->short_slug . '_license_action_button', array( $this, 'display_license_action_button' ) );

			// Send data to 1Updater
			add_filter( 'wpj_1updater_plugins', array( $this, 'wpjobster_1updater_plugin_add' ) );

			add_action( 'redux/options/jobster_settings/saved', array( $this, 'save_from_redux' ), 10, 1 );
			add_action( 'update_option_wpjobster_license_key', array( $this, 'save_to_redux' ), 1, 3 );
		}

		public function save_from_redux( $options ) {
			if ( get_option( 'wpjobster_' . $this->short_slug . '_license_key' ) != $options['wpjobster_' . $this->short_slug . '_license_key'] )
				update_option( 'wpjobster_' . $this->short_slug . '_license_key', $options['wpjobster_' . $this->short_slug . '_license_key'] );
		}

		public function save_to_redux( $old_value, $value, $option ) {
			if ( class_exists( 'Redux' ) ) Redux::set_option( 'jobster_settings', 'wpjobster_' . $this->short_slug . '_license_key', $value );
		}

		public function wpjobster_1updater_plugin_add( $plugins ) {

			$license = wpj_get_option( 'wpjobster_' . $this->short_slug . '_license_key' );
			$status  = get_option( 'wpjobster_' . $this->short_slug . '_license_status' );
			$details = get_option( 'wpjobster_' . $this->short_slug . '_license_status_details' );

			$plugins[] = (object) [
				'item_name'       => $this->item_name,
				'short_slug'      => $this->short_slug,
				'license_key'     => $license,
				'license_status'  => $status,
				'license_details' => $details,
				'type'            => $this->type
			];

			return $plugins;
		}


		public function updater() {

			// To support auto-updates, this needs to run during the wp_version_check cron job for privileged users.
			$doing_cron = defined( 'DOING_CRON' ) && DOING_CRON;
			if ( ! current_user_can( 'manage_options' ) && ! $doing_cron ) {
				return;
			}

			// retrieve our license key from the DB
			$license_key = trim( wpj_get_option( 'wpjobster_' . $this->short_slug . '_license_key' ) );

			// Setup the updater
			$edd_updater = new EDD_SL_Plugin_Updater(
				$this->api_url,
				$this->file,
				array(
					'version'   => $this->version,
					'license'   => $license_key,
					'item_name' => $this->item_name,
					'item_id'   => $this->item_id,
					'author'    => $this->author,
					'beta'      => false
				)
			);

			$this->sl_version = isset( $edd_updater->sl_version ) ? $edd_updater->sl_version : $this->sl_version;
		}

		public function display_license_action_button() {
			$status = get_option( 'wpjobster_' . $this->short_slug . '_license_status' );

			wp_nonce_field( 'wpjobster_' . $this->short_slug . '_nonce', 'wpjobster_' . $this->short_slug . '_nonce' );

			if ( 'valid' == $status ) { ?>

				<input type="submit" class="button-secondary" name="wpjobster_<?php echo $this->short_slug; ?>_license_deactivate" value="<?php _e( 'Deactivate License', $this->textdomain ); ?>"/>

			<?php } else { ?>

				<input type="submit" class="button-secondary" name="wpjobster_<?php echo $this->short_slug; ?>_license_activate" value="<?php _e( 'Activate License', $this->textdomain ); ?>"/>

			<?php }

		}

		public function sanitize_license( $new ) {
			$old = wpj_get_option( 'wpjobster_' . $this->short_slug . '_license_key' );
			if ( $old && $old != $new ) {
				// delete_option( 'wpjobster_' . $this->short_slug . '_license_active' );
				delete_option( 'wpjobster_' . $this->short_slug . '_license_status' ); // new license has been entered, so must reactivate
				delete_option( 'wpjobster_' . $this->short_slug . '_license_status_details' );
			}
			return $new;
		}

		public function license_url() {
			if ( isset( $_POST['jobster_settings']['redux-section'] ) && $_POST['jobster_settings']['redux-section'] == wpj_get_settings_tab_number_by_field_id( '1updater-settings' ) ) {
				$license_url = add_query_arg( array(
					'tab' => wpj_get_settings_tab_number_by_field_id( '1updater-settings' )
				), menu_page_url( 'jobster-settings', false ) );

			} else {
				$license_url = add_query_arg( array(
					'tab' => wpj_get_settings_tab_number_by_field_id( $this->short_slug . '-settings' )
				), menu_page_url( 'jobster-settings', false ) );
			}

			return $license_url;
		}

		public function activate_license() {

			// listen for our activate button to be clicked
			if ( isset( $_POST['wpjobster_' . $this->short_slug . '_license_activate'] ) ) {

				// run a quick security check
				if ( ! check_admin_referer( 'wpjobster_' . $this->short_slug . '_nonce', 'wpjobster_' . $this->short_slug . '_nonce' ) ) {
					return; // get out if we didn't click the Activate button
				}

				// retrieve the license from the database
				if ( isset( $_POST['wpjobster_' . $this->short_slug . '_license_key'] ) ) {
					$license = $_POST['wpjobster_' . $this->short_slug . '_license_key'];
					update_option( 'wpjobster_' . $this->short_slug . '_license_key', $license );
				} else {
					$license = trim( wpj_get_option( 'wpjobster_' . $this->short_slug . '_license_key' ) );
					if ( $license == '' && isset( $this->license ) ) {
						$license = trim( $this->license );
						update_option( 'wpjobster_' . $this->short_slug . '_license_key', $license );
					}
				}

				// data to send in our API request
				$api_params = array(
					'edd_action'  => 'activate_license',
					'license'     => $license,
					'item_name'   => urlencode( $this->item_name ), // the name of our product in EDD
					'item_id'     => $this->item_id,
					'url'         => home_url(),
					'environment' => function_exists( 'wp_get_environment_type' ) ? wp_get_environment_type() : 'production',
				);

				// Call the custom API.
				$response = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );

				// make sure the response came back okay
				if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {

					if ( is_wp_error( $response ) ) {
						$message = $response->get_error_message();
					} else {
						$message = __( 'An error occurred, please try again.', $this->textdomain );
					}

				} else {

					$license_data = wpj_json_decode( wp_remote_retrieve_body( $response ) );

					if ( false === $license_data->success ) {
						switch( $license_data->error ) {
							case 'expired' :

								$message = sprintf(
									__( 'Your license key expired on %s.', $this->textdomain ),
									date_i18n( get_option( 'date_format' ), strtotime( $license_data->expires, current_time( 'timestamp' ) ) )
								);
								break;

							case 'disabled' :
							case 'revoked' :

								$message = __( 'Your license key has been disabled.', $this->textdomain );
								break;

							case 'missing' :

								$message = __( 'Invalid license.', $this->textdomain );
								break;

							case 'invalid' :
							case 'site_inactive' :

								$message = __( 'Your license is not active for this URL.', $this->textdomain );
								break;

							case 'item_name_mismatch' :

								$message = sprintf( __( 'This appears to be an invalid license key for %s.', $this->textdomain ), $this->item_name );
								break;

							case 'no_activations_left':

								$message = __( 'Your license key has reached its activation limit.', $this->textdomain );
								break;

							default :

								$message = __( 'An error occurred, please try again.', $this->textdomain );
								break;
						}
					}
				}

				// Check if anything passed on a message constituting a failure
				if ( ! empty( $message ) ) {
					wp_redirect( add_query_arg( array(
						'sl_' . $this->short_slug . '_activation' => 'false',
						'message' => urlencode( $message ),
					), $this->license_url() ) );
					exit();
				}

				// $license_data->license will be either "valid" or "invalid"

				// update_option( 'wpjobster_' . $this->short_slug . '_license_active', $license_data );
				update_option( 'wpjobster_' . $this->short_slug . '_license_status', $license_data->license );

				$message = sprintf(
					__( 'Expires on %1$s. You have %2$s / %3$s sites activated.', $this->textdomain ),
					date_i18n( get_option( 'date_format' ), strtotime( $license_data->expires, current_time( 'timestamp' ) ) ),
					$license_data->site_count,
					$license_data->license_limit
				);

				update_option( 'wpjobster_' . $this->short_slug . '_license_status_details', $message );

				wp_redirect( $this->license_url() ); exit();
			}
		}


		public function deactivate_license() {

			// listen for our activate button to be clicked
			if ( isset( $_POST['wpjobster_' . $this->short_slug . '_license_deactivate'] ) ) {

				// run a quick security check
				if ( ! check_admin_referer( 'wpjobster_' . $this->short_slug . '_nonce', 'wpjobster_' . $this->short_slug . '_nonce' ) ) {
					return; // get out if we didn't click the Activate button
				}

				// retrieve the license from the input or the database
				if ( isset( $_POST['wpjobster_' . $this->short_slug . '_license_key'] ) ) {
					$license = $_POST['wpjobster_' . $this->short_slug . '_license_key'];
					update_option( 'wpjobster_' . $this->short_slug . '_license_key', $license );
				} else {
					$license = trim( wpj_get_option( 'wpjobster_' . $this->short_slug . '_license_key' ) );
					if ( $license == '' && isset( $this->license ) ) {
						$license = trim( $this->license );
						update_option( 'wpjobster_' . $this->short_slug . '_license_key', $license );
					}
				}

				// data to send in our API request
				$api_params = array(
					'edd_action'  => 'deactivate_license',
					'license'     => $license,
					'item_name'   => urlencode( $this->item_name ), // the name of our product in EDD
					'item_id'     => $this->item_id,
					'url'         => home_url(),
					'environment' => function_exists( 'wp_get_environment_type' ) ? wp_get_environment_type() : 'production',
				);

				// Call the custom API.
				$response = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );

				// make sure the response came back okay
				if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {

					if ( is_wp_error( $response ) ) {
						$message = $response->get_error_message();
					} else {
						$message = __( 'An error occurred, please try again.', $this->textdomain );
					}

					wp_redirect( add_query_arg( array(
						'sl_' . $this->short_slug . '_activation' => 'false',
						'message' => urlencode( $message ),
					), $this->license_url() ) );
					exit();
				}

				// decode the license data
				$license_data = wpj_json_decode( wp_remote_retrieve_body( $response ) );

				// $license_data->license will be either "deactivated" or "failed"
				if ( $license_data->license == 'deactivated' ) {
					// delete_option( 'wpjobster_' . $this->short_slug . '_license_active' );
					delete_option( 'wpjobster_' . $this->short_slug . '_license_status' );
					delete_option( 'wpjobster_' . $this->short_slug . '_license_status_details' );
				}

				wp_redirect( $this->license_url() ); exit();
			}
		}


		public function check_license() {

			global $wp_version;

			// retrieve the license from the database
			$license = trim( wpj_get_option( 'wpjobster_' . $this->short_slug . '_license_key' ) );

			if ( $license == '' && isset( $this->license ) ) {
				$license = trim( $this->license );
				update_option( 'wpjobster_' . $this->short_slug . '_license_key', $license );
			}

			$api_params = array(
				'edd_action'  => 'check_license',
				'license'     => $license,
				'item_name'   => urlencode( $this->item_name ),
				'item_id'     => $this->item_id,
				'url'         => home_url(),
				'environment' => function_exists( 'wp_get_environment_type' ) ? wp_get_environment_type() : 'production',
			);

			// Call the custom API.
			$response = wp_remote_post( $this->api_url, array( 'timeout' => 15, 'sslverify' => false, 'body' => $api_params ) );

			if ( is_wp_error( $response ) ) {
				return false;
			}

			$license_data = wpj_json_decode( wp_remote_retrieve_body( $response ) );

			if ( $license_data->license == 'valid' ) {
				echo 'valid'; exit;
				// this license is still valid
			} else {
				echo 'invalid'; exit;
				// this license is no longer valid
			}

			// TODO: update _license_active, _license_status, _license_status_details
		}

		public function register_option() {
			// creates our settings in the options table
			register_setting( 'wpjobster_' . $this->short_slug . '_license', 'wpjobster_' . $this->short_slug . '_license_key', array( $this, 'sanitize_license' ) );
		}

		public function wpjobster_admin_notices() {
			if ( isset( $_GET['sl_' . $this->short_slug . '_activation'] ) && ! empty( $_GET['message'] ) ) {

				switch( $_GET['sl_' . $this->short_slug . '_activation'] ) {

					case 'false':
						$message = urldecode( $_GET['message'] );
						?>
						<div class="error">
							<p><?php echo $message; ?></p>
						</div>
						<?php
						break;

					case 'true':
					default:
						// success message
						break;
				}
			}
		}

		public function plugin_row_license_missing( $plugin_data, $version_info ) {

			static $showed_imissing_key_message;

			$status = get_option( 'wpjobster_' . $this->short_slug . '_license_status' );

			if ( ( 'valid' !== $status ) && empty( $showed_imissing_key_message[ $this->short_slug ] ) ) {

				echo ' <em>' . sprintf(
					__( 'To enable updates, please <a href="%s">activate your license</a>.', $this->textdomain ),
					$this->license_url()
				) . '</em>';

				$showed_imissing_key_message[ $this->short_slug ] = true;
			}
		}
	}
} // end class_exists check


/**
 * Backwards compatibility with old WPJ_Gateway_License calls.
 *
 * @author WPJobster
 * @version 1.0.0
 */

if ( ! class_exists( 'WPJ_Gateway_License' ) ) {
	class WPJ_Gateway_License extends WPJ_Plugin_License {
		function __construct( $plugin_data ) {
			$plugin_data['type'] = 'gateway';
			parent::__construct( $plugin_data );
		}
	}
} // end class_exists check
