<?php
/**
 * GJM Admin Settings Page
 *
 * @package wpjm-jobs-geolocation
 */

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * GJM_Admin class
 */
class GJM_Admin_Settings {

	/**
	 * Options
	 *
	 * @var array
	 */
	public $settings = array();

	/**
	 * Prefix
	 *
	 * @var string
	 */
	public $prefix = 'gjm';

	/**
	 * Singular name
	 *
	 * @var string
	 */
	public $name_singular = 'job';

	/**
	 * Plural name.
	 *
	 * @var string
	 */
	public $name_plural = 'jobs';

	/**
	 * __construct function.
	 *
	 * @access public
	 * @return void
	 */
	public function __construct() {

		$this->settings = get_option( 'gjm_options' );

		// default settings - load only on Jobs settings page.
		if ( ! empty( $_GET['post_type'] ) && 'job_listing' === $_GET['post_type'] && ! empty( $_GET['page'] ) && 'job-manager-settings' === $_GET['page'] ) { // WPCS: CSRF ok.
			add_action( 'admin_init', array( $this, 'default_settings' ), 99 );
		}

		// hook custom function that creates the importer button.
		add_action( 'wp_job_manager_admin_field_gjm_locations_importer', array( $this, 'locations_importer_form' ) );
		// hook custom function that creates the importer button.
		add_action( 'wp_job_manager_admin_field_gjm_google_maps_server_api_key_test_button', array( $this, 'generate_google_maps_server_api_key_test_button' ) );

		// locations importer.
		add_action( 'admin_init', array( $this, 'locations_importer' ) );
		add_action( 'admin_init', array( $this, 'test_google_maps_server_api_key' ) );
		add_action( 'admin_notices', array( $this, 'admin_notices' ) );

		// admin settings - append GJM settings to WPJM settings page.
		add_filter( 'job_manager_settings', array( $this, 'admin_settings' ), 20 );

		// make sure we updating WPJM settings page to also update our settings - run this only on UPDATE settings.
		if ( ! empty( $_POST['action'] ) && 'update' === $_POST['action'] && ! empty( $_POST['option_page'] ) && 'job_manager' === $_POST['option_page'] ) { // WPCS: CSRF ok.
			add_action( 'admin_init', array( $this, 'options_validate' ), 10 );
		}
	}

	/**
	 * Default Settings.
	 *
	 * @return [type] [description]
	 */
	public function default_settings() {

		// only if no options set.
		if ( ! empty( $this->settings ) ) {
			return;
		}

		$options = array(
			'general_settings' => array(),
			'search_form'      => array(
				$this->prefix . '_auto_locator'    => 1,
				$this->prefix . '_locator_button'  => 1,
				$this->prefix . '_radius'          => '10,15,25,50,100',
				$this->prefix . '_units'           => 'both',
				$this->prefix . '_orderby'         => 'distance,title,featured,date',
				$this->prefix . '_map_width'       => '100%',
				$this->prefix . '_map_height'      => '250px',
				$this->prefix . '_map_type'        => 'ROADMAP',
				$this->prefix . '_group_markers'   => 'markers_clusterer',
				$this->prefix . '_user_marker'     => 'https://maps.google.com/mapfiles/ms/icons/blue-dot.png',
				$this->prefix . '_location_marker' => 'https://maps.google.com/mapfiles/ms/icons/red-dot.png',
				$this->prefix . '_clusters_path'   => 'https://raw.githubusercontent.com/googlemaps/js-marker-clusterer/gh-pages/images/m',
				$this->prefix . '_zoom_level'      => 'auto',
				$this->prefix . '_max_zoom_level'  => '',
				$this->prefix . '_scroll_wheel'    => 1,
				$this->prefix . '_distance'        => 1,
				$this->prefix . '_pages_enabled'   => array(),
			),
			'single_page'      => array(
				$this->prefix . '_single_map_enabled'      => 'top',
				$this->prefix . '_single_map_width'        => '100%',
				$this->prefix . '_single_map_height'       => '200px',
				$this->prefix . '_single_map_type'         => 'ROADMAP',
				$this->prefix . '_single_map_location_marker' => 'https://maps.google.com/mapfiles/ms/icons/red-dot.png',
				$this->prefix . '_single_map_scroll_wheel' => 1,
			),
		);

		// save each field in its own database option.
		// we do this because thats how WP Job Manager saves its options and display them again on page load.
		foreach ( $options as $groups ) {
			foreach ( $groups as $field => $value ) {
				update_option( $field, $value );
			}
		}

		// update default options into single database option.
		update_option( $this->prefix . '_options', $options );
	}

	/**
	 * Admin Notices.
	 *
	 * @return void
	 */
	public function admin_notices() {

		// check if notice exist.
		if ( empty( $_GET['gjm_notice'] ) ) { // WPCS: CSRF ok.
			return;
		}

		$notice           = ! empty( $_GET['gjm_notice'] ) ? sanitize_text_field( wp_unslash( $_GET['gjm_notice'] ) ) : ''; // WPCS: CSRF ok.
		$status           = ! empty( $_GET['gjm_notice_status'] ) ? sanitize_text_field( wp_unslash( $_GET['gjm_notice_status'] ) ) : ''; // WPCS: CSRF ok.
		$locations        = ! empty( $_GET['number_of_locations'] ) ? sanitize_text_field( wp_unslash( $_GET['number_of_locations'] ) ) : 0; // WPCS: CSRF ok.
		$api_test_message = get_option( 'gjm_server_api_key_error_message' );

		$messages                                 = array();
		$messages['locations_import_nonce_error'] = __( 'There was an error while trying to import locations.', 'pointify' );
		$messages['no_locations_to_import']       = __( 'No locations to import were found.', 'pointify' );
		$messages['no_locations_imported']        = __( 'No locations were imported.', 'pointify' );
		// translators: %d for number of locations.
		$messages['locations_imported'] = sprintf( __( '%d Locations successfully imported.', 'pointify' ), $locations );
		// translators: %s for error message.
		$messages['server_api_key_test_failed'] = sprintf( __( 'Google Maps Server API key test failed. Error message: %s', 'pointify' ), $api_test_message );
		$messages['server_api_key_test_pass']   = __( 'Your Google Maps server API key seems to be working properly.', 'pointify' );

		?>
		<div class="<?php echo esc_attr( $status ); ?>" style="display:block;margin-top:10px;">
			<p><?php echo $messages[ $notice ]; // XSS ok. ?></p>
		</div>
		<?php
	}

	/**
	 * Generate the Google Maps Server API key test button.
	 *
	 * @param  [type] $option [description].
	 */
	public function generate_google_maps_server_api_key_test_button( $option ) {
		?>
		<input 
			type="button" 
			id="gjm-google-maps-server-api-key-test-button" 
			class="button-secondary" 
			value="<?php _e( 'Test API Key', 'pointify' ); // WPCS: XSS ok. ?>"
			onclick="jQuery('#gjm_google_maps_server_api_key_test_hidden').prop( 'disabled', false); jQuery(this).closest('form').submit();" 
		/>

		<input 
			type="hidden" 
			id="gjm_google_maps_server_api_key_test_hidden" 
			name="gjm_google_maps_server_api_key_test_action" 
			value="1" disabled="disabled" 
		/>

		<p class="description"><?php esc_attr( $option['desc'] ); ?></p>

		<?php wp_nonce_field( 'gjm_google_maps_server_api_key_test', 'gjm_google_maps_server_api_key_test' ); ?>
		<?php
	}

	/**
	 * Test the Google Maps Server API key.
	 *
	 * @return [type] [description]
	 */
	public function test_google_maps_server_api_key() {

		if ( empty( $_POST['gjm_google_maps_server_api_key_test_action'] ) ) {
			return;
		}

		// look for nonce.
		if ( empty( $_POST['gjm_google_maps_server_api_key_test'] ) ) {
			return;
		}

		// varify nonce.
		if ( ! wp_verify_nonce( $_POST['gjm_google_maps_server_api_key_test'], 'gjm_google_maps_server_api_key_test' ) ) { // WPCS: CSRF ok, XSS ok, sanitization ok.
			return;
		}

		$api_key = get_option( 'job_manager_google_maps_api_key' );
		$url     = 'https://maps.googleapis.com/maps/api/geocode/json?key=' . esc_attr( $api_key ) . '&address=manhattan+ny+us&language=en';
		$result  = wp_remote_get(
			$url,
			[
				'timeout'     => 5,
				'redirection' => 1,
				'httpversion' => '1.1',
				'user-agent'  => 'WordPress/WP-Job-Manager-' . JOB_MANAGER_VERSION . '; ' . esc_url( home_url() ),
				'sslverify'   => false,
			]
		);

		$failed_message = __( 'Failed connecting to remote server.', 'pointify' );
		$failed_url     = 'edit.php?post_type=job_listing&page=job-manager-settings&gjm_notice=server_api_key_test_failed&gjm_notice_status=error';

		// abort if no data found.
		if ( is_wp_error( $result ) ) {

			update_option( 'gjm_server_api_key_error_message', $failed_message );

			wp_safe_redirect( admin_url( $failed_url ) );

			exit;
		}

		// look for geocoded data.
		$geocoded_data = wp_remote_retrieve_body( $result );

		// abort if no data found.
		if ( is_wp_error( $geocoded_data ) ) {

			update_option( 'gjm_server_api_key_error_message', $failed_message );

			wp_safe_redirect( admin_url( $failed_url ) );

			exit;
		}

		$geocoded_data = json_decode( $geocoded_data );

		if ( 'OK' !== $geocoded_data->status ) {

			$status  = 0;
			$message = ! empty( $geocoded_data->error_message ) ? $geocoded_data->error_message : 'Unknown error';

			update_option( 'gjm_server_api_key_error_message', $message );

		} else {

			$status = 1;
		}

		// redirect and exist.
		if ( empty( $status ) ) {
			wp_safe_redirect( admin_url( $failed_url ) );
		} else {
			wp_safe_redirect( admin_url( 'edit.php?post_type=job_listing&page=job-manager-settings&gjm_notice=server_api_key_test_pass&gjm_notice_status=updated' ) );
		}

		exit;
	}

	/**
	 * Generate the locations importer button
	 *
	 * @param  array $option options.
	 */
	public function locations_importer_form( $option ) {
		?>
		<input 
			type="button" 
			id="gjm-locations-import-toggle" 
			class="button-secondary" 
			value="<?php _e( 'Import', 'pointify' ); // WPCS: XSS ok. ?>"
			onclick="jQuery('#gjm_import_hidden').prop( 'disabled', false); jQuery(this).closest('form').submit();" 
		/>

		<input 
			type="hidden" 
			id="gjm_import_hidden" 
			name="gjm_import_action" 
			value="<?php echo esc_attr( $this->prefix ); ?>" disabled="disabled" 
		/>

		<p class="description"><?php esc_attr( $option['desc'] ); ?></p>

		<?php wp_nonce_field( $this->prefix . '_locations_import_nonce', $this->prefix . '_locations_import_nonce' ); ?>
		<?php
	}

	/**
	 * Locations importer.
	 *
	 * @return void
	 */
	public function locations_importer() {

		if ( empty( $_POST['gjm_import_action'] ) ) {
			return;
		}

		$prefix = $_POST['gjm_import_action']; // WPCS: CSRF ok, sanitization ok.

		// get prefix.
		if ( 'gjm' === $prefix ) {
			$post_type = 'job_listing';
			$page_name = 'job-manager-settings';
		} else {
			$post_type = 'resume';
			$page_name = 'resume-manager-settings';
		}

		// varify nonce.
		if ( empty( $_POST[ $prefix . '_locations_import_nonce' ] ) || ! wp_verify_nonce( $_POST[ $prefix . '_locations_import_nonce' ], $prefix . '_locations_import_nonce' ) ) { // WPCS: CSRF ok, sanitization ok.
			wp_safe_redirect( admin_url( 'edit.php?post_type=' . $post_type . '&page=' . $page_name . '&gjm_notice=locations_import_nonce_error&gjm_notice_status=error' ) );
		}

		// import locations.
		$imported = GJM_Admin::import_locations( $post_type );

		// redirect and exist.
		if ( empty( $imported ) ) {
			wp_safe_redirect( admin_url( 'edit.php?post_type=' . $post_type . '&page=' . $page_name . '&gjm_notice=no_locations_imported&gjm_notice_status=error' ) );
		} else {
			wp_safe_redirect( admin_url( 'edit.php?post_type=' . $post_type . '&page=' . $page_name . '&gjm_notice=locations_imported&number_of_locations=' . $imported . '&gjm_notice_status=updated' ) );
		}

		exit;
	}

	/**
	 * Get existing WordPress pages
	 */
	public function get_pages() {

		$pages = array();

		foreach ( get_pages() as $page ) {
			$pages[ $page->ID ] = $page->post_title;
		}

		return $pages;
	}

	/**
	 * Multiselect field type.
	 *
	 * @param  array  $option      [description].
	 * @param  array  $attributes  [description].
	 * @param  mixed  $value       [description].
	 * @param  string $placeholder [description].
	 */
	public function multiselect_type( $option, $attributes, $value, $placeholder ) {

		?>
		<select 
			multiple="multiple" 
			data-placeholder="Select pages..." 
			id="setting-<?php echo esc_attr( $option['name'] ); ?>" 
			class="regular-text" 
			name="<?php echo esc_attr( $option['name'] ); ?>[]"
			<?php echo implode( ' ', $attributes ); ?>
		>
		<?php

		if ( ! is_array( $value ) || empty( $value ) ) {
			$value = array();
		}

		if ( in_array( 'front_page', $value, true ) ) {
			$front_selected = 'selected="selected"';
		} else {
			$front_selected = '';
		}

		echo '<option value="front_page" ' . $front_selected . '>Home / Front Page</option>'; // WPCS: XSS ok.

		foreach ( $option['options'] as $key => $name ) {

			$selected = '';

			if ( in_array( $key, $value ) ) {
				$selected = 'selected="selected"';
			}

			echo '<option value="' . esc_attr( $key ) . '" ' . $selected . '>' . esc_html( $name ) . '</option>'; // WPCS: XSS ok.
		}

		if ( ! wp_script_is( 'select2', 'enqueued' ) ) {
			wp_enqueue_style( 'select2' );
		}
		?>
		</select>

		<?php $chosen_id = '#setting-' . $this->prefix . '_enabled_pages'; ?>

		<script>
		jQuery( document ).ready( function() {
			if ( jQuery.fn.select2 ) {
				jQuery( '<?php echo esc_attr( $chosen_id ); ?>' ).select2();
			}
		});
		</script>
		<?php

		if ( $option['desc'] ) {
			echo ' <p class="description">' . esc_attr( $option['desc'] ) . '</p>';
		}

		// enable chosen for the multiselect.
		wp_enqueue_script( 'chosen', JOB_MANAGER_PLUGIN_URL . '/assets/js/jquery-chosen/chosen.jquery.min.js', array( 'jquery' ), '1.1.0', true );
		wp_enqueue_style( 'chosen', JOB_MANAGER_PLUGIN_URL . '/assets/css/chosen.css', array(), '1.1.0', true );
	}

	/**
	 * Admin settings page
	 *
	 * @param  array $settings settings.
	 *
	 * @return array.
	 */
	public function admin_settings( $settings ) {

		$prefix = $this->prefix;

		add_action( 'wp_job_manager_admin_field_' . $prefix . '_multiselect', array( $this, 'multiselect_type' ), 50, 4 );

		$is_gjm_settings_page = false;

		if ( ( isset( $_GET['page'] ) && 'job-manager-settings' === $_GET['page'] ) || ( isset( $_POST['option_page'] ) && 'update' === $_POST['action'] && 'job_manager' === $_POST['option_page'] ) ) { // WPCS: CSRF ok,.

			$is_gjm_settings_page = true;
		}

		// apply only for WP Job Manager settings page.
		if ( $is_gjm_settings_page ) {

			// API Key test button options.
			$settings['general'][1][] = array(
				'name'       => 'gjm_google_maps_server_api_key_test_button',
				'type'       => 'gjm_google_maps_server_api_key_test_button',
				'std'        => '',
				'label'      => __( 'Google Maps Server API Key Testing Tool', 'pointify' ),
				'desc'       => __( 'Click here to test and verify that your Google Maps API Key is working properly.', 'pointify' ),
				'attributes' => array(),
			);
			
		}

		return $settings;
	}

	/**
	 * Validate the updated values and return them to be saved in gjm_options single option.
	 * i like keeping all the options saved in a single array which can later be pulled with
	 * a single call to database instead of multiple calles per option
	 */
	public function options_validate() {

		$prefix = $this->prefix;

		$valid_input = array();

		foreach ( $this->admin_settings( array() ) as $section_name => $section ) {

			$sn = str_replace( 'gjm_', '', $section_name );

			foreach ( $section[1] as $option ) {

				if ( empty( $option['type'] ) ) {
					continue;
				}

				switch ( $option['type'] ) {

					case 'checkbox':
						$valid_input[ $sn ][ $option['name'] ] = ( ! empty( $_POST[ $option['name'] ] ) ) ? 1 : 0; // WPCS: CSRF ok.
						$_POST[ $option['name'] ]              = $valid_input[ $sn ][ $option['name'] ];
						break;

					case 'select':
						if ( ! empty( $_POST[ $option['name'] ] ) && in_array( $_POST[ $option['name'] ], array_keys( $option['options'] ) ) ) { // WPCS: CSRF ok.
							$valid_input[ $sn ][ $option['name'] ] = sanitize_text_field( wp_unslash( $_POST[ $option['name'] ] ) ); // WPCS: CSRF ok.
						} else {

							$valid_input[ $sn ][ $option['name'] ] = ( ! empty( $option['std'] ) ) ? $option['std'] : '';
							$_POST[ $option['name'] ]              = $valid_input[ $sn ][ $option['name'] ];
						}
						break;

					case $prefix . '_multiselect':
						if ( ! empty( $_POST[ $option['name'] ] ) && is_array( $_POST[ $option['name'] ] ) ) { // WPCS: CSRF ook.

							$valid_input[ $sn ][ $option['name'] ] = sanitize_text_field( wp_unslash( $_POST[ $option['name'] ] ) ); // WPCS: CSRF ok.

						} else {

							$valid_input[ $sn ][ $option['name'] ] = array();
							$_POST[ $option['name'] ]              = array();
						}
						break;

					case 'text':
						if ( ! empty( $_POST[ $option['name'] ] ) ) { // WPCS: CSRF oko.
							$valid_input[ $sn ][ $option['name'] ] = sanitize_text_field( wp_unslash( $_POST[ $option['name'] ] ) ); // WPCS: CSRF ok.
							$_POST[ $option['name'] ]              = $valid_input[ $sn ][ $option['name'] ];
						} else {
							$valid_input[ $sn ][ $option['name'] ] = ( ! empty( $option['std'] ) ) ? $option['std'] : '';
							$_POST[ $option['name'] ]              = $valid_input[ $sn ][ $option['name'] ];
						}
						break;
				}
			}
		}

		update_option( $prefix . '_options', $valid_input );
	}
}
new GJM_Admin_Settings();
