<?php

class WPML_Page_Name_Query_Filter{

	private $current_language;
	private $active_languages;
	private $al_regexp;

	public function __construct( $active_languages ) {
		global $sitepress;

		$this->current_language    = $sitepress->get_current_language();
		$this->active_languages[ ] = $this->current_language;
		unset( $active_languages[ $this->current_language ] );
		$this->active_languages = array_merge ( $this->active_languages, array_keys ( $active_languages ) );
		$this->al_regexp        = $this->generate_al_regexp ( $this->active_languages );
	}

	public function set_current_lang() {
		global $sitepress;

		$this->active_languages = array_unique (
			array_merge ( array( $sitepress->get_current_language () ), $this->active_languages )
		);
	}

	public function filter_page_name( $page_query ) {

		foreach ( array( 'name', 'pagename' ) as $index ) {
			list( $pages_with_name, $page_name_for_query ) = $this->query_needs_adjustment( $page_query, $index );

			if ( (bool) $pages_with_name === true ) {
				global $wpml_post_translations;

				foreach ( $this->active_languages as $lang_code ) {
					foreach ( $pages_with_name as $p_with_name ) {
						if ( $wpml_post_translations->get_element_lang_code( $p_with_name ) === $lang_code ) {
							$pid = $p_with_name;
							break;
						}
					}
					if ( isset( $pid ) ) {
						break;
					}
				}

				if ( isset( $pid ) ) {
					$page_query = $this->maybe_adjust_query_by_pid( $page_query, $pid, $index );
				} elseif ( (bool) $page_name_for_query === true ) {
					$page_query->query_vars[ $index ]    = $page_name_for_query;
					$page_query->query_vars['post_type'] = 'page';
				}
			}
		}

		return $page_query;
	}

	private function maybe_adjust_query_by_pid( $page_query, $pid, $index ) {
		if ( ! ( isset( $page_query->queried_object )
		         && isset( $page_query->queried_object->ID )
		         && $page_query->queried_object->ID == $pid )
		) {
			$page_query->query_vars['page_id'] = $pid;
			unset( $page_query->query_vars[ $index ] );
			unset( $page_query->queried_object );
			if ( $page_query->query_vars['page_id'] == get_option( 'page_for_posts' ) ) {
				// it's the blog page.
				$page_query->is_page       = false;
				$page_query->is_home       = true;
				$page_query->is_posts_page = true;
			}
		}

		return $page_query;
	}

	private function generate_al_regexp( $active_language_codes ) {

		return '/^(' . implode ( '|', $active_language_codes ) . ')\//';
	}

	private function query_needs_adjustment( $page_query, $index ) {

		if ( empty( $page_query->query_vars[$index] ) ) {
			$pages_with_name = false;
			$page_name_for_query = false;
		} else {
			$this->set_current_lang();
			// find the page with the page name in the current language.
			$page_name_for_query = preg_replace( $this->al_regexp, '', $page_query->query_vars[$index] );
			if ( strpos( $page_name_for_query, '/' ) === false ) {
				$pages_with_name = $this->get_single_slug_adjusted_IDs( $page_name_for_query );
			} else {
				$pages_with_name = $this->get_multiple_slug_adjusted_IDs( explode( '/', $page_name_for_query ) );
			}

			if ( (bool) $pages_with_name === false
			     || ( count( $pages_with_name ) === 1
			          && isset( $page_query->queried_object )
			          && isset( $page_query->queried_object->ID )
			          && $page_query->queried_object->ID == $pages_with_name[0]
			     )
			) {

				$pages_with_name =  false;
			}
		}

		return array($pages_with_name, $page_name_for_query);
	}

	private function get_single_slug_adjusted_IDs($page_name_for_query){
		global $wpdb;

		$pages_with_name                 = $wpdb->get_col (
			$wpdb->prepare (
				"
				SELECT ID
				FROM $wpdb->posts p
				JOIN {$wpdb->prefix}icl_translations t
					ON p.ID = t.element_id AND element_type='post_page'
				WHERE p.post_name = %s
				ORDER BY p.post_parent = 0 DESC
				",
				$page_name_for_query
			)
		);

		return $pages_with_name;
	}

	private function get_multiple_slug_adjusted_IDs( $slugs ) {
		global $wpdb;

		$parent_slugs = array_slice($slugs, 0, -1);

		$pages_with_name = $wpdb->get_results(
			"	SELECT p.ID, p.post_name, p.post_parent, par.post_name as parent_name
				FROM $wpdb->posts p
				JOIN {$wpdb->prefix}icl_translations t
					ON p.ID = t.element_id AND element_type='post_page'
				LEFT JOIN $wpdb->posts par
					ON par.ID = p.post_parent
				WHERE p.post_name IN (" . wpml_prepare_in( $slugs ) . ")
				ORDER BY par.post_name IN (" . wpml_prepare_in( $parent_slugs ) .") DESC"
		);

		foreach ( $pages_with_name as $key => $page ) {
			if ( $page->parent_name ) {
				$slug_pos     = array_search( $page->post_name, $slugs, true );
				$par_slug_pos = array_search( $page->parent_name, $slugs, true );
				if ( $par_slug_pos !== false && $slug_pos !== false && $slug_pos - $par_slug_pos !== 1 ) {
					unset( $pages_with_name[ $key ] );
				}
			}
		}

		$possible_ids = array();

		foreach ( $pages_with_name as $key => $page ) {
			$correct_slug        = end( $slugs );
			if ( $page->post_name === $correct_slug ) {
				$possible_ids[] = $page->ID;
			} else {
				unset( $pages_with_name[ $key ] );
			}
		}

		return $possible_ids;
	}
}