<?php
/**
 * GJM Functions file.
 *
 * @package wpjm-jobs-geolocation.
 */

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

/**
 * GJM Labels
 *
 * @return labels to be used in the plugin. Labels can be modified using the filter 'gjm_form_labels'
 */
function gjm_labels() {

	$labels = apply_filters(
		'gjm_form_labels',
		array(
			'miles'           => __( 'Miles', 'pointify' ),
			'kilometers'      => __( 'Kilometers', 'pointify' ),
			'within'          => __( 'Within', 'pointify' ),
			'orderby_filters' => array(
				'label'    => __( 'Sort', 'pointify' ),
				'distance' => __( 'Distance', 'pointify' ),
				'title'    => __( 'Title', 'pointify' ),
				'featured' => __( 'Featured', 'pointify' ),
				'date'     => __( 'Date', 'pointify' ),
				'modified' => __( 'Last Updated', 'pointify' ),
				'ID'       => __( 'ID', 'pointify' ),
				'parent'   => __( 'Parent', 'pointify' ),
				'rand'     => __( 'Random', 'pointify' ),
				'name'     => __( 'Name', 'pointify' ),
			),
			'search_result'   => array(
				'company'   => __( 'Company:', 'pointify' ),
				'address'   => __( 'Address:', 'pointify' ),
				'job_types' => __( 'Job Types:', 'pointify' ),
				// translators: %s for data.
				'posted'    => __( 'Posted %s ago', 'pointify' ),
				'mi'        => __( 'mi', 'pointify' ),
				'km'        => __( 'km', 'pointify' ),
			),
			'resize_map'      => __( 'Resize map', 'pointify' ),
		)
	);

	return $labels;
}

/**
 * Single Job Page map.
 *
 * @param string $prefix plugin's prefix gjm || grm.
 *
 * @param string $post_type job_listing || resume.
 */
function gjm_single_page_map( $prefix = 'gjm', $post_type = 'job_listing' ) {

	global $post;

	// verfy that we are in a single job post type.
	if ( $post->post_type !== $post_type ) {
		return;
	}

	$settings = get_option( $prefix . '_options' );
	$settings = $settings['single_page'];

	global $wpdb;

	$location = $wpdb->get_row(
		$wpdb->prepare(
			"SELECT *, `long` as lng FROM {$wpdb->prefix}places_locator WHERE post_id = %d",
			$post->ID
		)
	); // WPCS: db call ok, cache ok.

	if ( empty( $location ) || empty( $location->lat ) || empty( $location->long ) || '0.000000' === $location->lat ) {
		return;
	}

	$location->map_icon = $settings[ $prefix . '_single_map_location_marker' ];

	$element_id = 'job_map_listing';
	$map_args   = array(
		'map_id'         => $element_id,
		'prefix'         => $prefix,
		'map_width'      => $settings[ $prefix . '_single_map_width' ],
		'map_height'     => $settings[ $prefix . '_single_map_height' ],
		'init_map_show'  => true,
		'zoom_level'     => ! empty( $settings[ $prefix . '_single_map_zoom_level' ] ) ? $settings[ $prefix . '_single_map_zoom_level' ] : 12,
		'max_zoom_level' => ! empty( $settings[ $prefix . '_single_map_max_zoom_level' ] ) ? $settings[ $prefix . '_single_map_max_zoom_level' ] : '',
		'map_type'       => $settings[ $prefix . '_single_map_type' ],
		'scrollwheel'    => $settings[ $prefix . '_single_map_scroll_wheel' ],
		'map_name'       => 'single-page',
	);

	$map = '';

	if ( class_exists( 'GJM_Maps' ) ) {

		// Generate the map element.
		$map = GJM_Maps::get_map_element( $map_args );

		// create the map object.
		$map_args = array(
			'map_id' => $element_id,
			'prefix' => $prefix,
		);

		$map_args = GJM_Maps::get_map_object( $map_args, array(), array( $location ), array() );
	}

	echo $map; // WPCS: XSS ok.
}

/**
 * Load map on single page
 */
function gjm_enable_single_page_map() {

	$gjm_options    = get_option( 'gjm_options' );
	$current_filter = current_filter();

	// in preview submission page.
	if ( ! empty( $_POST['submit_job'] ) && 'Preview' === $_POST['submit_job'] ) { // WPCS: CSRF ok.

		if ( apply_filters( 'gjm_form_preview_map', true ) && 'single_job_listing_start' === $current_filter ) {
			gjm_single_page_map();
		}

		// in single job page.
	} else {

		$single_page_option = $gjm_options['single_page']['gjm_single_map_enabled'];

		if ( ( 'top' === $single_page_option && 'single_job_listing_start' === $current_filter ) || ( 'bottom' === $single_page_option && 'single_job_listing_end' === $current_filter ) ) {

			gjm_single_page_map();
		}
	}

	remove_action( $current_filter, 'gjm_enable_single_page_map', 50 );
}
add_action( 'single_job_listing_map', 'gjm_enable_single_page_map', 50 );

/**
 * Enable address autocomplete for the Front-end job form
 *
 * @return [type] [description]
 */
function gjm_address_autocomplete_front_end() {

	$settings = get_option( 'gjm_options' );

	if ( empty( $settings['general_settings']['gjm_address_autocomplete_form_frontend'] ) ) {
		return;
	}

	GJM_Init::enqueue_google_maps_api();

	wp_enqueue_script( 'gjm-autocomplete' );
}
add_action( 'submit_job_form_job_fields_start', 'gjm_address_autocomplete_front_end' );

/**
 * Additional details for info window
 *
 * This data was available in previous versions of the plugin, but was removed since
 * version 2.0 for the purpose of a cleaner info-window and improve performance.
 *
 * To enable this info back use the filter 'gjm_info_window_additional_details' to return true.
 *
 * @param  object $post post object.
 * @return [type]       [description]
 */
function gjm_info_window_additional_info( $post ) {

	$labels = gjm_labels();

	$company = the_company_name( '', '', false, $post );

	if ( empty( $company ) ) {
		$company = __( 'N/A', 'pointify' );
	}

	$job_type_slug = '';
	$job_type_name = '';

	// for version 1.27 or higer.
	if ( function_exists( 'wpjm_get_the_job_types' ) ) {

		$job_types = wpjm_get_the_job_types( $post->ID );

		// before 1.27.
	} else {

		$job_types = get_the_job_type( $post );
		$job_types = ! empty( $job_types ) ? array( $job_types ) : array();
	}

	if ( ! empty( $job_types ) ) {

		$job_type_names = array();
		$job_type_slugs = array();

		foreach ( $job_types as $type ) {
			$job_type_names[] = $type->name;
			$job_type_slugs[] = sanitize_title( $type->slug );
		}

		$job_type_names = implode( ', ', $job_type_names );
		$job_type_slugs = implode( ' ', $job_type_slugs );

	} else {

		$job_type_names = __( 'N/A', 'pointify' );
		$job_type_slugs = 'na';
	}

	$output = array();

	$output['items_start'] = '<ul class="job-items">';

	$output['company'] = '<li class="compny-name"><span class="label">' . esc_attr( $labels['search_result']['company'] ) . ' </span><span class="item">' . esc_attr( $company ) . '</span></li>';

	$output['job_types'] = '<li class="job-types ' . esc_attr( $job_type_slugs ) . '"><span class="label">' . esc_attr( $labels['search_result']['job_types'] ) . ' </span><span class="item">' . esc_attr( $job_type_names ) . '</span></li>';

	$output['posted'] = '<li class="date"><span class="item"><date>' . sprintf( $labels['search_result']['posted'], human_time_diff( get_post_time( 'U', false, $post ), current_time( 'timestamp' ) ) ) . '</date></li>';

	$output['items_end'] = '</ul>';

	return $output;
}

/**
 * Delete location from database.
 *
 * From Jobs Geolocation and GEO my WP database tables.
 *
 * @param  integer $post_id post ID.
 */
function gjm_delete_location( $post_id = 0 ) {

	global $wpdb;

	$gmw = ( class_exists( 'GEO_my_WP' ) && version_compare( GMW_VERSION, '3.0', '>=' ) && class_exists( 'GMW_Location' ) ) ? true : false;

	$wpdb->query(
		$wpdb->prepare(
			'DELETE FROM ' . $wpdb->prefix . 'places_locator WHERE post_id=%d',
			$post_id
		)
	); // WPCS: db call ok, cache ok.

	if ( $gmw && function_exists( 'gmw_delete_location_by_object' ) ) {
		gmw_delete_location_by_object( 'post', $post_id );
	}
}

/**
 * Update location in database.
 *
 * In Jobs Geolocation and GEO my WP database tables.
 *
 * @param  integer $post_id post ID.
 *
 * @param  array   $values  location data.
 */
function gjm_update_location( $post_id = 0, $values = array() ) {

	global $wpdb;

	$gmw = ( class_exists( 'GEO_my_WP' ) && version_compare( GMW_VERSION, '3.0', '>=' ) && class_exists( 'GMW_Location' ) ) ? true : false;

	$street_number = sanitize_text_field( get_post_meta( $post_id, 'geolocation_street_number', true ) );
	$street_name   = sanitize_text_field( get_post_meta( $post_id, 'geolocation_street', true ) );
	$street_check  = trim( $street_number . ' ' . $street_name );
	$street        = ! empty( $street_check ) ? $street_number . ' ' . $street_name : '';

	$title   = ! empty( $values['title'] ) ? sanitize_text_field( $values['title'] ) : '';
	$address = ! empty( $values['address'] ) ? sanitize_text_field( $values['address'] ) : '';
	$email   = ! empty( $values['email'] ) ? sanitize_text_field( $values['email'] ) : '';

	$city         = sanitize_text_field( get_post_meta( $post_id, 'geolocation_city', true ) );
	$region_code  = sanitize_text_field( get_post_meta( $post_id, 'geolocation_state_short', true ) );
	$region_name  = sanitize_text_field( get_post_meta( $post_id, 'geolocation_state_long', true ) );
	$postcode     = sanitize_text_field( get_post_meta( $post_id, 'geolocation_postcode', true ) );
	$country_code = sanitize_text_field( get_post_meta( $post_id, 'geolocation_country_short', true ) );
	$country_name = sanitize_text_field( get_post_meta( $post_id, 'geolocation_country_long', true ) );

	$formatted_address = sanitize_text_field( get_post_meta( $post_id, 'geolocation_formatted_address', true ) );
	$lat               = sanitize_text_field( get_post_meta( $post_id, 'geolocation_lat', true ) );
	$lng               = sanitize_text_field( get_post_meta( $post_id, 'geolocation_long', true ) );

	$wpdb->replace(
		$wpdb->prefix . 'places_locator',
		array(
			'post_id'           => $post_id,
			'feature'           => 0,
			'post_type'         => get_post_type( $post_id ),
			'post_title'        => $title,
			'post_status'       => 'publish',
			'street_number'     => $street_number,
			'street_name'       => $street_name,
			'street'            => $street,
			'apt'               => '',
			'city'              => $city,
			'state'             => $region_code,
			'state_long'        => $region_name,
			'zipcode'           => $postcode,
			'country'           => $country_code,
			'country_long'      => $country_name,
			'address'           => $address,
			'formatted_address' => $formatted_address,
			'phone'             => '',
			'fax'               => '',
			'email'             => $email,
			'website'           => '',
			'lat'               => $lat,
			'long'              => $lng,
			'map_icon'          => '_default.png',
		)
	); // WPCS: db call ok, cache ok.

	if ( $gmw ) {

		$location_args = array(
			'object_type'       => 'post',
			'object_id'         => (int) $post_id,
			'user_id'           => (int) get_post_field( 'post_author', $post_id ),
			'parent'            => 0,
			'status'            => 1,
			'featured'          => 0,
			'title'             => $title,
			'latitude'          => $lat,
			'longitude'         => $lng,
			'street_number'     => $street_number,
			'street_name'       => $street_name,
			'street'            => $street,
			'premise'           => '',
			'neighborhood'      => '',
			'city'              => $city,
			'county'            => '',
			'region_name'       => $region_name,
			'region_code'       => $region_code,
			'postcode'          => $postcode,
			'country_name'      => $country_name,
			'country_code'      => $country_code,
			'address'           => $address,
			'formatted_address' => $formatted_address,
			'place_id'          => '',
			'map_icon'          => '_default.png',
		);

		// save location.
		$location_id = GMW_Location::update( $location_args );

		if ( ! empty( $email ) ) {
			gmw_update_location_meta( $location_id, 'email', $email );
		}
	}
}

/**
 * Add new job to GJM table in database.
 *
 * @param integer $post_id post ID.
 *
 * @param array   $values  location data.
 *
 * @since  1.0.
 *
 * @author Eyal Fitoussi
 */
function gjm_update_location_front_end( $post_id, $values ) {

	$geolocated = get_post_meta( $post_id, 'geolocated', true );
	$gmw        = ( class_exists( 'GEO_my_WP' ) && version_compare( GMW_VERSION, '3.0', '>=' ) && class_exists( 'GMW_Location' ) ) ? true : false;

	// delete location if address field empty.
	if ( empty( $values['job']['job_location'] ) || empty( $geolocated ) ) {

		gjm_delete_location( $post_id, $gmw );

	} else {

		$location_values = array();

		$location_values['title']   = sanitize_text_field( $values['job']['job_title'] );
		$location_values['address'] = ! empty( $values['job']['job_location'] ) ? sanitize_text_field( $values['job']['job_location'] ) : '';
		$location_values['email']   = ! empty( $values['job']['application'] ) ? sanitize_text_field( $values['job']['application'] ) : '';

		gjm_update_location( $post_id, $location_values, $gmw );
	}
}
add_action( 'job_manager_update_job_data', 'gjm_update_location_front_end', 50, 2 );

/**
 * Import locations.
 *
 * This function imports existing jobs location from the custom fields
 *
 * into the locations data table.
 *
 * @param  string $post_type job_listing || resume.
 *
 * @return [type]            [description]
 */
function gjm_import_locations( $post_type = 'job_listing' ) {

	if ( 'resume' === $post_type ) {
		$post_type = 'resume';
	} else {
		$post_type = 'job_listing';
	}

	global $wpdb;

	// Get all posts with posts types jobs or resume.
	$posts = $wpdb->get_results(
		"
		SELECT `ID` as 'post_id', `post_title`, `post_type`, `post_status`
		FROM `{$wpdb->prefix}posts`
		WHERE `post_type` = '{$post_type}'
		",
		ARRAY_A
	); // WPCS: db call ok, cache ok, unprepared SQL ok.

	// Abort if no posts found.
	if ( empty( $posts ) ) {
		return false;
	}

	// Number of locations imported.
	$imported = 0;

	// Loop the found posts.
	foreach ( $posts as $post_key => $post_info ) {

		// Check if location already exists in database.
		$check_location = $wpdb->get_col(
			$wpdb->prepare(
				"
				SELECT `post_id` 
				FROM `{$wpdb->prefix}places_locator` 
				WHERE `post_id` = %d",
				$post_info['post_id']
			),
			0
		); // WPCS: db call ok, cache ok.

		// Skip location if exist in gmw table.
		if ( ! empty( $check_location ) ) {
			continue;
		}

		// Get all jobs or resume location custom fields.
		$post_location = $wpdb->get_results(
			$wpdb->prepare(
				"
				SELECT `meta_key`, `meta_value`
				FROM `{$wpdb->prefix}postmeta`
				WHERE `post_id` = %d
				AND `meta_key` IN ( 'geolocation_street', 'geolocation_city', 'geolocation_state_short', 'geolocation_state_long', 'geolocation_postcode',
			'geolocation_country_short', 'geolocation_country_long', 'geolocation_lat', 'geolocation_long', 'geolocation_formatted_address')",
				$post_info['post_id']
			),
			ARRAY_A
		); // WPCS: db call ok, cache ok.

		// Loop custom fields and add them to array of posts.
		foreach ( $post_location as $location_key => $location ) {
			$posts[ $post_key ][ $location['meta_key'] ] = $location['meta_value']; // WPCS: slow query ok.
		}

		// Verify coordinates.
		if ( empty( $posts[ $post_key ]['geolocation_lat'] ) || empty( $posts[ $post_key ]['geolocation_long'] ) ) {
			continue;
		}

		$values = array(
			'object_id'         => $posts[ $post_key ]['post_id'],
			'featured'          => 0,
			'status'            => $posts[ $post_key ]['post_status'],
			'post_type'         => $post_type,
			'title'             => $posts[ $post_key ]['post_title'],
			'latitude'          => $posts[ $post_key ]['geolocation_lat'],
			'longitude'         => $posts[ $post_key ]['geolocation_long'],
			'street'            => $posts[ $post_key ]['geolocation_street'],
			'apt'               => '',
			'city'              => $posts[ $post_key ]['geolocation_city'],
			'region_code'       => $posts[ $post_key ]['geolocation_state_short'],
			'region_name'       => $posts[ $post_key ]['geolocation_state_long'],
			'postcode'          => $posts[ $post_key ]['geolocation_postcode'],
			'country_code'      => $posts[ $post_key ]['geolocation_country_short'],
			'country_name'      => $posts[ $post_key ]['geolocation_country_long'],
			'address'           => $posts[ $post_key ]['geolocation_formatted_address'],
			'formatted_address' => $posts[ $post_key ]['geolocation_formatted_address'],
			'map_icon'          => 'default.png',
		);

		// create entry in database.
		$created = $wpdb->query(
			$wpdb->prepare(
				"INSERT INTO `{$wpdb->prefix}places_locator` ( 
				`post_id`, 
				`feature`, 
				`post_status`, 
				`post_type`, 
				`post_title`, 
				`lat`,
				`long`, 
				`street`, 
				`apt`, 
				`city`, 
				`state`, 
				`state_long`, 
				`zipcode`, 
				`country`,
				`country_long`, 
				`address`, 
				`formatted_address`, 
				`map_icon` 
			)
			VALUES ( %d, %d, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s )",
				$values
			)
		); // WPCS: db call ok, cache ok, PreparedSQLPlaceholders replacement count ok.

		if ( $created ) {
			$imported++;
		}
	}

	return $imported;
}

/**
 * Generate geocoding status message below the address field of the Edit Job/Resume pages.
 *
 * @param  int    $post_id       Post ID.
 *
 * @param  string $address_field ID attribbute of the address field.
 *
 * @return [type]                [description]
 */
function gjm_address_geocoding_status_message( $post_id, $address_field = '_job_location' ) {

	$post_id = absint( $post_id );

	// get the address.
	$address = get_post_meta( $post_id, $address_field, true );

	// Abort. No need to show a message when no address provided.
	if ( empty( $address ) ) {
		return;
	}

	// get geocoding status.
	$geocoded = get_post_meta( $post_id, 'geolocated', true );

	// Show success message when geocoding successful.
	if ( ! empty( $geocoded ) ) {

		$color   = '#73a724';
		$message = 'Address geocoded successfully.';
		$icon    = 'dashicons-yes-alt';

		// Othwerwise, show error message.
	} else {
		$color   = '#a00';
		$message = 'The address is not yet geocoded. Click the "Publish" button to geocode the address.';
		$icon    = 'dashicons-editor-help';
	}

	// Generate the message.
	$output  = '<em class="gjm-address-geocoding-status" style="color:' . $color . ';line-height: 14px;font-size: 12px;margin-top: 4px;display: inline-block;float:right;">';
	$output .= '<span class="dashicons ' . $icon . '" style="font-size: 15px;line-height: 13px;width: 16px;"></span>';
	$output .= $message;
	$output .= '</span></em>';
	?>
	<script>
		jQuery( document ).ready( function() {
			jQuery( '#' + '<?php echo esc_attr( $address_field ); ?>' ).closest( '.form-field' ).append( '<?php echo $output; ?>' ); // WPCS: XSS ok.
		});
	</script>
	<?php
}
