<?php if ( ! class_exists( 'WPJ_Search_SQL_Filters' ) ) {
	class WPJ_Search_SQL_Filters extends stdClass {

		/**
		 * @param mixed $_args
		 * @param mixed $_search_args
		 * @param mixed $_post_type
		 */
		public function __construct( $_args, $_search_args, $_post_type ) {
			global $wpdb;

			$this->args        = $_args;
			$this->search_args = $_search_args;
			$this->post_type   = $_post_type;
			$this->wpdb        = $wpdb;
		}

		public function add_search_filters() {
			// use before WP Query and remove immediately after

			// add search term query
			if ( ! empty( $this->search_args['term'] ) ) {
				if ( $this->post_type == 'job' || $this->post_type == '' ) {
					add_filter( 'posts_where' , [ $this, 'job_posts_where' ] );

				} elseif ( $this->post_type == 'request' ) {
					add_filter( 'posts_where' , [ $this, 'request_posts_where' ] );

				}
			}

			// conditionally add filters for location
			if ( ! empty( $this->search_args['location'] ) ) {
				if ( $this->post_type == 'job' || $this->post_type == '' ) {
					add_filter( 'posts_fields', [ $this, 'job_posts_fields' ] );
					add_filter( 'posts_join_paged', [ $this, 'job_posts_join' ] );
					add_filter( 'posts_groupby', [ $this, 'job_posts_group_by' ] );
					add_filter( 'posts_orderby', [ $this, 'job_posts_order_by' ] );

				} elseif ( $this->post_type == 'request' ) {
					add_filter( 'posts_fields', [ $this, 'request_posts_fields' ] );
					add_filter( 'posts_join_paged', [ $this, 'request_posts_join' ] );
					add_filter( 'posts_groupby', [ $this, 'request_posts_group_by' ] );
					add_filter( 'posts_orderby', [ $this, 'request_posts_order_by' ] );

				}
			}
		}

		public function remove_search_filters() {
			// remove filters just after the WP_Query where we need them
			// and before other queries to prevent them being affected
			// especially when suppress_filters doesn't work

			remove_filter( 'posts_where' , [ $this, 'job_posts_where' ] );
			remove_filter( 'posts_where' , [ $this, 'request_posts_where' ] );

			remove_filter( 'posts_fields', [ $this, 'job_posts_fields' ] );
			remove_filter( 'posts_join_paged', [ $this, 'job_posts_join' ] );
			remove_filter( 'posts_groupby', [ $this, 'job_posts_group_by' ] );
			remove_filter( 'posts_orderby', [ $this, 'job_posts_order_by' ] );

			remove_filter( 'posts_fields', [ $this, 'request_posts_fields' ] );
			remove_filter( 'posts_join_paged', [ $this, 'request_posts_join' ] );
			remove_filter( 'posts_groupby', [ $this, 'request_posts_group_by' ] );
			remove_filter( 'posts_orderby', [ $this, 'request_posts_order_by' ] );
		}

		// START Search job filters //

		/**
		 * @param $where
		 * @return string
		 */
		public function job_posts_where( $where ) {
			$term = $this->search_args['term'];

			if ( ! is_array( $term ) ) {
				$terms = trim( $term );
				$term = explode( " ", $terms );

			} else {
				$term = [];

			}

			$xl = '';

			foreach ( $term as $tt ) {
				$xl .= " AND ({$this->wpdb->posts}.post_title LIKE '%$tt%' OR {$this->wpdb->posts}.post_content LIKE '%$tt%' )";
			}

			$where .= " AND (1=1 $xl )";

			return $where;
		}

		/**
		 * @param $select
		 * @return string
		 */
		public function job_posts_fields( $select ) {
			$units = wpj_get_option( 'wpjobster_locations_unit' ) == 'kilometers' ? 6371 : 3959;

			if ( ! empty( $this->search_args['latitude'] ) && ! empty( $this->search_args['longitude'] ) ) {
				return $select . ", {$units} * acos( cos( radians({$this->search_args['latitude']}) ) * cos( radians( wpj_lat.meta_value ) ) * cos( radians ( wpj_long.meta_value ) - radians({$this->search_args['longitude']}) ) + sin( radians({$this->search_args['latitude']}) ) * sin( radians ( wpj_lat.meta_value ) ) ) as distance";
			}

			return $select;
		}

		/**
		 * @param $join
		 * @return string
		 */
		public function job_posts_join( $join ) {
			$join = $join . "
				LEFT JOIN {$this->wpdb->prefix}postmeta AS wpj_lat ON ({$this->wpdb->prefix}posts.ID = wpj_lat.post_id AND wpj_lat.meta_key = 'lat' )
				LEFT JOIN {$this->wpdb->prefix}postmeta AS wpj_long ON ({$this->wpdb->prefix}posts.ID = wpj_long.post_id AND wpj_long.meta_key = 'long' )
			";

			return $join;
		}

		/**
		 * @param $groupby
		 * @return string
		 */
		public function job_posts_group_by( $groupby ) {
			$rad = ! empty( $this->search_args['radius'] ) ? $this->search_args['radius'] : wpj_get_option( 'wpj_locations_radius_default' );

			if ( ! empty( $this->search_args['latitude'] ) && ! empty( $this->search_args['longitude'] ) ) {
				$groupby = $groupby . "
					HAVING distance < {$rad}
				";
			}

			return $groupby;
		}

		/**
		 * @param $orderby
		 * @return string
		 */
		public function job_posts_order_by( $orderby ) {
			if ( $this->args['orderby'] == 'distance' ) {
				$orderby = "
					distance ASC
				";
			}

			return $orderby;
		}

		// END Search job filters //

		// START Search request filters //

		/**
		 * @param $where
		 * @return string
		 */
		public function request_posts_where( $where ) {
			$term = $this->search_args['term'];

			if ( ! is_array( $term ) ) {
				$terms = trim( $term );
				$term = explode( " ", $terms );

			} else {
				$term = [];

			}

			$xl = '';

			foreach ( $term as $tt ) {
				$xl .= " AND ({$this->wpdb->posts}.post_title LIKE '%$tt%' OR {$this->wpdb->posts}.post_content LIKE '%$tt%' )";
			}

			$where .= " AND (1=1 $xl )";

			return $where;
		}

		/**
		 * @param $select
		 * @return string
		 */
		public function request_posts_fields( $select ) {
			$units = wpj_get_option( 'wpjobster_locations_unit' ) == 'kilometers' ? 6371 : 3959;

			if ( ! empty( $this->search_args['latitude'] ) && ! empty( $this->search_args['longitude'] ) ) {
				$select = $select . ",
					{$units} * acos( cos( radians({$this->search_args['latitude']}) ) * cos( radians( wpj_lat.meta_value ) ) * cos( radians ( wpj_long.meta_value ) - radians({$this->search_args['longitude']}) ) + sin( radians({$this->search_args['latitude']}) ) * sin( radians ( wpj_lat.meta_value ) ) ) as distance,
					{$units} * acos( cos( radians({$this->search_args['latitude']}) ) * cos( radians( wpj_lat_pick_up.meta_value ) ) * cos( radians ( wpj_long_pick_up.meta_value ) - radians({$this->search_args['longitude']}) ) + sin( radians({$this->search_args['latitude']}) ) * sin( radians ( wpj_lat_pick_up.meta_value ) ) ) as distance_pick_up,
					{$units} * acos( cos( radians({$this->search_args['latitude']}) ) * cos( radians( wpj_lat_drop_off.meta_value ) ) * cos( radians ( wpj_long_drop_off.meta_value ) - radians({$this->search_args['longitude']}) ) + sin( radians({$this->search_args['latitude']}) ) * sin( radians ( wpj_lat_drop_off.meta_value ) ) ) as distance_drop_off
				";
			}

			return $select;
		}

		/**
		 * @param $join
		 * @return string
		 */
		public function request_posts_join( $join ) {
			$join = $join . "
				LEFT JOIN {$this->wpdb->prefix}postmeta AS wpj_lat ON ({$this->wpdb->prefix}posts.ID = wpj_lat.post_id AND wpj_lat.meta_key = 'request_lat' )
				LEFT JOIN {$this->wpdb->prefix}postmeta AS wpj_long ON ({$this->wpdb->prefix}posts.ID = wpj_long.post_id AND wpj_long.meta_key = 'request_long' )
				LEFT JOIN {$this->wpdb->prefix}postmeta AS wpj_lat_pick_up ON ({$this->wpdb->prefix}posts.ID = wpj_lat_pick_up.post_id AND wpj_lat_pick_up.meta_key = 'request_pick_up_lat' )
				LEFT JOIN {$this->wpdb->prefix}postmeta AS wpj_long_pick_up ON ({$this->wpdb->prefix}posts.ID = wpj_long_pick_up.post_id AND wpj_long_pick_up.meta_key = 'request_pick_up_long' )
				LEFT JOIN {$this->wpdb->prefix}postmeta AS wpj_lat_drop_off ON ({$this->wpdb->prefix}posts.ID = wpj_lat_drop_off.post_id AND wpj_lat_drop_off.meta_key = 'request_drop_off_lat' )
				LEFT JOIN {$this->wpdb->prefix}postmeta AS wpj_long_drop_off ON ({$this->wpdb->prefix}posts.ID = wpj_long_drop_off.post_id AND wpj_long_drop_off.meta_key = 'request_drop_off_long' )
			";

			return $join;
		}

		/**
		 * @param $groupby
		 * @return string
		 */
		public function request_posts_group_by( $groupby ) {
			$rad = ! empty( $this->search_args['radius'] ) ? $this->search_args['radius'] : wpj_get_option( 'wpj_locations_radius_default' );

			if ( ! $groupby ) {
				$groupby = $this->wpdb->posts . '.ID';
			}

			$groupby = $groupby . "
				HAVING distance < {$rad} OR distance_pick_up < {$rad} OR distance_drop_off < {$rad}
			";

			return $groupby;
		}

		/**
		 * @param $orderby
		 * @return string
		 */
		public function request_posts_order_by( $orderby ) {
			if ( $this->args['orderby'] == 'distance' ) {
				$orderby = "
					distance ASC
				";
			}

			return $orderby;
		}
	}
}