<?php
namespace SabaiApps\Directories\Platform\WordPress;

use SabaiApps\Directories\Context;

class Template {

	private static $_instance;
	private $_application, $_context, $_headHtml, $_jsHtml, $_pageIds, $_skipInTheLoopCheck, $_currentTheme;

	public function __construct( Platform $platform ) {
		$this->_application = $platform->getApplication();

		// Fetch now otherwise will be cleared when widgets are rendered
		$this->_headHtml = $platform->getHeadHtml();
		$this->_jsHtml   = $platform->getJsHtml();

		$page_slugs     = $platform->getPageSlugs();
		$this->_pageIds = (array) $page_slugs[2];

		$this->_currentTheme = strtolower( wp_get_theme( get_template() )->get( 'Name' ) );
		$this->_maybeAddThemeSpecificFilters( $platform, $this->_currentTheme );
	}

	protected function _maybeAddThemeSpecificFilters( Platform $platform, $theme ) {
		switch ( $theme ) {
			case 'enfold':
				add_filter(
					'avf_title_args',
					function ( $args ) use ( $platform ) {
						if ( is_tax()
						&& isset( $GLOBALS['wp_query'] )
						&& ( $term = $GLOBALS['wp_query']->get_queried_object() )
						&& ( $term_bundle = $this->_application->Entity_Bundle( $term->taxonomy ) )
						) {
							$args['title'] = sprintf( $term_bundle->getLabel( 'page' ), $term->name );
						}
						return $args;
					}
				);
				break;
			default:
		}
	}

	public static function getInstance( Platform $platform ) {
		if ( ! isset( self::$_instance ) ) {
			self::$_instance = new self( $platform );
		}
		return self::$_instance;
	}

	public function setContext( Context $context ) {
		$this->_context = $context;
		return $this;
	}

	public function render() {
		add_action( 'wp_head', array( $this, 'onWpHeadAction' ) );
		add_action( 'wp_footer', array( $this, 'onWpFooterAction' ), 99 );
		add_filter( 'body_class', array( $this, 'onBodyClassFilter' ) );

		// Hook with 3rd party breadcrumb plugins
		if ( defined( 'WC_VERSION' ) ) {
			add_filter( 'woocommerce_get_breadcrumb', array( $this, 'onWoocommerceGetBreadcrumbFilter' ) );
		}
		if ( defined( 'WPSEO_VERSION' ) ) {
			add_filter( 'wpseo_breadcrumb_links', array( $this, 'onWpseoBreadcrumbLinksFilter' ) );
		}
		if ( class_exists( '\breadcrumb_navxt', false ) ) {
			add_action( 'bcn_after_fill', array( $this, 'onBcnAfterFillAction' ) );
		}
		if ( class_exists( '\RankMath', false ) ) {
			add_filter( 'rank_math/frontend/breadcrumb/items', array( $this, 'onRankmathFrontendBreadcrumbItemsFilter' ), 10, 2 );
		}
		if ( $this->_currentTheme === 'blocksy' ) {
			add_filter( 'blocksy:breadcrumbs:items-array', array( $this, 'onBlocksyBreadcrumbsItemsArrayFilter' ) );
		}

		if ( isset( $this->_context ) ) {
			add_filter( 'the_title', array( $this, 'onTheTitleFilter' ), PHP_INT_MAX - 1, 2 );
		}
		return $this;
	}

	public function onWpHeadAction() {
		echo $this->_headHtml;
	}

	public function onWpFooterAction() {
		echo $this->_jsHtml;
	}

	public function onBodyClassFilter( $classes ) {
		if ( isset( $this->_context ) ) {
			$route     = $this->_context->getRoute();
			$classes[] = 'drts-' . strtolower( $route->controller_component . '-' . $route->controller );
		}
		return $classes;
	}

	public function onWoocommerceGetBreadcrumbFilter( $crumbs ) {
		if ( isset( $GLOBALS['drts_entity'] ) ) {
			if ( $page = $this->_getArchivePageForBreadcrumbs() ) {
				$home = array_shift( $crumbs );
			}

			// Add taxonomy term crumbs?
			if ( $GLOBALS['drts_entity']->getType() === 'post' ) {
				if ( ( $tax_bundle_type = apply_filters( 'drts_wordpress_breadcrumbs_tax_type', null, $GLOBALS['drts_entity'] ) )
					&& ( $term = $GLOBALS['drts_entity']->getSingleFieldValue( $tax_bundle_type ) )
				) {
					array_unshift( $crumbs, array( $term->getTitle(), get_term_link( $term->getId(), $term->getBundleName() ) ) );
					// Add crumbs for parent terms if any
					if ( $parent_terms = get_ancestors( $term->getId(), $term->getBundleName(), 'taxonomy' ) ) {
						foreach ( $parent_terms as $term_id ) {
							$parent_term = get_term( $term_id, $term->getBundleName() );
							if ( $parent_term instanceof \WP_Term ) {
								array_unshift( $crumbs, array( $parent_term->name, get_term_link( $parent_term->term_id, $term->getBundleName() ) ) );
							}
						}
					}
				}
			} elseif ( $GLOBALS['drts_entity']->getType() === 'term' ) {
				// Remove taxonomy name
				array_shift( $crumbs );
			} elseif ( $GLOBALS['drts_entity']->getType() === 'user' ) {
				if ( $page ) {
					array_shift( $crumbs ); // remove single item page
				}
				$crumbs[] = array(
					$GLOBALS['drts_entity']->getTitle(),
					home_url( $GLOBALS['wp']->request ), // current URL
				);
			}

			if ( isset( $home ) ) {
				// Add custom archive page
				array_unshift( $crumbs, array( $page->post_title, get_permalink( $page ) ) );
				// Add back home
				array_unshift( $crumbs, $home );
			}

			// WC does not seem to include parent post in crumbs, so add it if any
			if ( $GLOBALS['drts_entity']->getType() === 'post' ) {
				if ( ( $parent_post_id = $GLOBALS['drts_entity']->getParentId() )
					&& ( $parent_post = get_post( $parent_post_id ) )
				) {
					$current_post = array_pop( $crumbs );
					$crumbs[]     = array( $parent_post->post_title, get_permalink( $parent_post ) );
					$crumbs[]     = $current_post;
				}
			}

			// Add link to entity permalink if on an action page
			if ( get_query_var( 'drts_action' ) ) {
				$current_post = array_pop( $crumbs );
				$crumbs[]     = array( $this->_getEntityTitle( $GLOBALS['drts_entity'] ), $current_post[1] );
				$crumbs[]     = array( $this->_context->getTitle() );
			}
		}
		return $crumbs;
	}

	protected function _getEntityTitle( $entity ) {
		$title = $entity->getTitle();
		return strlen( $title ) ? $title : __( '(no title)', 'directories-pro' );
	}

	public function onWpseoBreadcrumbLinksFilter( $crumbs ) {
		if ( isset( $GLOBALS['drts_entity'] ) ) {
			if ( isset( $crumbs[0]['url'] )
				&& rtrim( $crumbs[0]['url'], '/' ) === home_url()
			) {
				// Remove home link added by WPSEO
				$home = array_shift( $crumbs );
			}

			if ( $GLOBALS['drts_entity']->getType() === 'post' ) {
				// Add taxonomy term crumbs?
				if ( $tax_bundle_type = apply_filters( 'drts_wordpress_breadcrumbs_tax_type', 'location_location', $GLOBALS['drts_entity'] ) ) {
					$term = $GLOBALS['drts_entity']->getSingleFieldValue( $tax_bundle_type );
				}
			} elseif ( $GLOBALS['drts_entity']->getType() === 'term' ) {
				// Remove taxonomy name
				array_shift( $crumbs );
				$term = $GLOBALS['drts_entity'];
			} elseif ( $GLOBALS['drts_entity']->getType() === 'user' ) {
				array_shift( $crumbs ); // remove single item page
				$crumbs[] = array(
					'text' => $GLOBALS['drts_entity']->getTitle(),
					'url'  => home_url( $GLOBALS['wp']->request ), // current URL
				);
			}

			// Add taxonomy archive pages
			if ( ! empty( $term ) ) {
				array_unshift(
					$crumbs,
					array(
						'text' => $term->getTitle(),
						'url'  => get_term_link( $term->getId(), $term->getBundleName() ),
					)
				);
				// Add crumbs for parent terms if any
				if ( $parent_terms = get_ancestors( $term->getId(), $term->getBundleName(), 'taxonomy' ) ) {
					foreach ( $parent_terms as $term_id ) {
						$parent_term = get_term( $term_id, $term->getBundleName() );
						if ( $parent_term instanceof \WP_Term ) {
							array_unshift(
								$crumbs,
								array(
									'text' => $parent_term->name,
									'url'  => get_term_link( $parent_term->term_id, $term->getBundleName() ),
								)
							);
						}
					}
				}
				// Add taxonomy archive page if single term page
				if ( $GLOBALS['drts_entity']->getType() === 'term' ) {
					if ( $tax_bundle = $this->_application->Entity_Bundle( $term->getBundleName() ) ) {
						$tax_bundle_path = $tax_bundle->getPath();
						if ( $tax_bundle_page = get_page_by_path( trim( $tax_bundle_path, '/' ) ) ) {
							array_unshift(
								$crumbs,
								array(
									'text' => $tax_bundle_page->post_title,
									'url'  => (string) $this->_application->Url( $tax_bundle_path ),
								)
							);
						}
					}
				}
			}
			// Add custom archive page
			if ( $page = $this->_getArchivePageForBreadcrumbs() ) {
				array_unshift(
					$crumbs,
					array(
						'url'  => get_permalink( $page ),
						'text' => $page->post_title,
					)
				);
			}
			// Add back home
			if ( isset( $home ) ) {
				array_unshift( $crumbs, $home );
			}

			// Add link to post permalink if on an action page
			if ( get_query_var( 'drts_action' ) ) {
				$action_crumb = array_pop( $crumbs );
				array_push(
					$crumbs,
					array(
						'url'  => get_permalink( $GLOBALS['drts_entity']->getId() ),
						'text' => $this->_getEntityTitle( $GLOBALS['drts_entity'] ),
					)
				);
				array_push( $crumbs, $action_crumb );
			}
		}
		return $crumbs;
	}

	public function onRankmathFrontendBreadcrumbItemsFilter( $crumbs, $class ) {
		if ( isset( $GLOBALS['drts_entity'] ) ) {
			if ( \RankMath\Helper::get_settings( 'general.breadcrumbs_home' ) ) {
				$home = array_shift( $crumbs );
			}

			if ( $GLOBALS['drts_entity']->getType() === 'post' ) {
				// Add taxonomy term crumbs?
				if ( ( $tax_bundle_type = apply_filters( 'drts_wordpress_breadcrumbs_tax_type', 'location_location', $GLOBALS['drts_entity'] ) )
					&& ( $term = $GLOBALS['drts_entity']->getSingleFieldValue( $tax_bundle_type ) )
				) {
					array_unshift(
						$crumbs,
						array(
							$term->getTitle(),
							get_term_link( $term->getId(), $term->getBundleName() ),
							'hide_in_schema' => false,
						)
					);
				}
			} elseif ( $GLOBALS['drts_entity']->getType() === 'term' ) {
				// Remove taxonomy name
				array_shift( $crumbs );
				$term = $GLOBALS['drts_entity'];
			} elseif ( $GLOBALS['drts_entity']->getType() === 'user' ) {
				array_shift( $crumbs ); // remove single item page
				array_push(
					$crumbs,
					array(
						$GLOBALS['drts_entity']->getTitle(),
						home_url( $GLOBALS['wp']->request ), // current URL
						'hide_in_schema' => false,
					)
				);
			}

			// Add taxonomy archive pages
			if ( isset( $term ) ) {
				// Add crumbs for parent terms if any
				if ( $parent_terms = get_ancestors( $term->getId(), $term->getBundleName(), 'taxonomy' ) ) {
					foreach ( $parent_terms as $term_id ) {
						$parent_term = get_term( $term_id, $term->getBundleName() );
						if ( $parent_term instanceof \WP_Term ) {
							array_unshift(
								$crumbs,
								array(
									$parent_term->name,
									get_term_link( $parent_term->term_id, $term->getBundleName() ),
									'hide_in_schema' => false,
								)
							);
						}
					}
				}
				// Add taxonomy archive page if single term page
				if ( $GLOBALS['drts_entity']->getType() === 'term' ) {
					if ( $tax_bundle = $this->_application->Entity_Bundle( $term->getBundleName() ) ) {
						$tab_bundle_path = $tax_bundle->getPath();
						if ( $tax_bundle_page = get_page_by_path( trim( $tab_bundle_path, '/' ) ) ) {
							array_unshift(
								$crumbs,
								array(
									$tax_bundle_page->post_title,
									(string) $this->_application->Url( $tax_bundle_path ),
									'hide_in_schema' => false,
								)
							);
						}
					}
				}
			}
			// Add custom archive page
			if ( $page = $this->_getArchivePageForBreadcrumbs() ) {
				array_unshift(
					$crumbs,
					array(
						$page->post_title,
						get_permalink( $page ),
						'hide_in_schema' => false,
					)
				);
			}
			// Add back home
			if ( isset( $home ) ) {
				array_unshift( $crumbs, $home );
			}

			// Add link to post permalink if on an action page
			if ( get_query_var( 'drts_action' ) ) {
				$action_crumb = array_pop( $crumbs );
				array_push(
					$crumbs,
					array(
						$this->_getEntityTitle( $GLOBALS['drts_entity'] ),
						get_permalink( $GLOBALS['drts_entity']->getId() ),
						'hide_in_schema' => false,
					)
				);
				array_push( $crumbs, array( $this->_context->getTitle(), null ) );
			}
		}

		return $crumbs;
	}

	public function onBlocksyBreadcrumbsItemsArrayFilter( $crumbs ) {
		if ( isset( $GLOBALS['drts_entity'] ) ) {
			$home = array_shift( $crumbs );

			if ( $GLOBALS['drts_entity']->getType() === 'post' ) {

			} elseif ( $GLOBALS['drts_entity']->getType() === 'term' ) {
				$term = $GLOBALS['drts_entity'];
				if ( $tax_bundle = $this->_application->Entity_Bundle( $term->getBundleName() ) ) {
					$tab_bundle_path = $tax_bundle->getPath();
					if ( $tax_bundle_page = get_page_by_path( trim( $tab_bundle_path, '/' ) ) ) {
						array_unshift(
							$crumbs,
							array(
								'name' => $tax_bundle_page->post_title,
								'url'  => (string) $this->_application->Url( $tab_bundle_path ),
							)
						);
					}
				}
			} elseif ( $GLOBALS['drts_entity']->getType() === 'user' ) {
				array_shift( $crumbs ); // remove single item page
				array_push(
					$crumbs,
					array(
						'name' => $GLOBALS['drts_entity']->getTitle(),
						'url'  => home_url( $GLOBALS['wp']->request ), // current URL
					)
				);
			}

			if ( $page = $this->_getArchivePageForBreadcrumbs() ) {
				// Add custom archive page
				array_unshift(
					$crumbs,
					array(
						'name' => $page->post_title,
						'url'  => get_permalink( $page ),
					)
				);
			}
			// Add back home
			array_unshift( $crumbs, $home );

			// Add link to post permalink if on an action page
			if ( get_query_var( 'drts_action' ) ) {
				array_push(
					$crumbs,
					array(
						'name' => $this->_getEntityTitle( $GLOBALS['drts_entity'] ),
						'url'  => get_permalink( $GLOBALS['drts_entity']->getId() ),
					)
				);
				array_push(
					$crumbs,
					array(
						'name' => $this->_context->getTitle(),
						'url'  => null,
					)
				);
			}
		} elseif ( ( $parent_pagename = get_query_var( 'drts_parent_pagename' ) )
				&& ( $parent_page = get_page_by_path( $parent_pagename ) )
			) {

				$current_page = array_pop( $crumbs );

				// Replace parent page with the one with correct title
				array_pop( $crumbs );
				array_push(
					$crumbs,
					array(
						'name' => $parent_page->post_title,
						'url'  => get_permalink( $parent_page ),
					)
				);

				array_push( $crumbs, $current_page );
		}

		return $crumbs;
	}

	public function onBcnAfterFillAction( $bcnBreadcrumbTrail ) {
		if ( isset( $GLOBALS['drts_entity'] ) ) {
			if ( ! empty( $bcnBreadcrumbTrail->opt['bhome_display'] ) ) {
				$home = array_pop( $bcnBreadcrumbTrail->breadcrumbs );
			}

			if ( $GLOBALS['drts_entity']->getType() === 'post' ) {

			} elseif ( $GLOBALS['drts_entity']->getType() === 'term' ) {
				$term = $GLOBALS['drts_entity'];
				// Add crumbs for parent terms if any
				if ( $parent_terms = get_ancestors( $term->getId(), $term->getBundleName(), 'taxonomy' ) ) {
					foreach ( $parent_terms as $term_id ) {
						$parent_term = get_term( $term_id, $term->getBundleName() );
						if ( $parent_term instanceof \WP_Term ) {
							$bcnBreadcrumbTrail->add(
								new \bcn_breadcrumb(
									$parent_term->name,
									$bcnBreadcrumbTrail->opt[ 'Htax_' . $term->getBundleName() . '_template' ],
									array( 'taxonomy', $term->getBundleName() ),
									get_term_link( $parent_term->term_id, $term->getBundleName() ),
									$parent_term->term_id
								)
							);
						}
					}
				}
				if ( $tax_bundle = $this->_application->Entity_Bundle( $term->getBundleName() ) ) {
					$tab_bundle_path = $tax_bundle->getPath();
					if ( $tax_bundle_page = get_page_by_path( trim( $tab_bundle_path, '/' ) ) ) {
						$bcnBreadcrumbTrail->add(
							new \bcn_breadcrumb(
								$tax_bundle_page->post_title,
								$bcnBreadcrumbTrail->opt['Hpost_page_template'],
								array( 'post', 'post-page' ),
								(string) $this->_application->Url( $tax_bundle_path ),
							)
						);
					}
				}
			} elseif ( $GLOBALS['drts_entity']->getType() === 'user' ) {
				array_shift( $bcnBreadcrumbTrail->breadcrumbs ); // remove single item page
				array_unshift(
					$bcnBreadcrumbTrail->breadcrumbs,
					new \bcn_breadcrumb( $GLOBALS['drts_entity']->getTitle() )
				);
			}

			// Add custom archive page
			if ( $page = $this->_getArchivePageForBreadcrumbs() ) {
				$bcnBreadcrumbTrail->add(
					new \bcn_breadcrumb(
						$page->post_title,
						$bcnBreadcrumbTrail->opt['Hpost_page_template'],
						array( 'post', 'post-page' ),
						get_permalink( $page ),
						$page->ID
					)
				);
			}
			if ( isset( $home ) ) {
				// Add back home
				$bcnBreadcrumbTrail->add( $home );
			}

			// Add link to post permalink if on an action page
			if ( get_query_var( 'drts_action' ) ) {
				$post_crumb = array_shift( $bcnBreadcrumbTrail->breadcrumbs );
				$post_crumb->set_title( $this->_getEntityTitle( $GLOBALS['drts_entity'] ) );
				$post_crumb->set_url( get_permalink( $GLOBALS['drts_entity']->getId() ) );
				array_unshift( $bcnBreadcrumbTrail->breadcrumbs, $post_crumb );
				array_unshift( $bcnBreadcrumbTrail->breadcrumbs, new \bcn_breadcrumb( $this->_context->getTitle() ) );
			}
		}
	}

	protected function _getArchivePageForBreadcrumbs() {
		if ( ! $page_name = get_query_var( 'drts_parent_pagename' ) ) {
			if ( isset( $GLOBALS['drts_entity'] )
				&& $GLOBALS['drts_entity']->getType() === 'term'
			) {
				// Single taxonomy term page with same slug as single post page
				$page_name = get_query_var( 'drts_pagename' );
			}
		}
		if ( $page_name
			&& ( $page = get_page_by_path( $page_name ) )
			&& ( get_option( 'show_on_front' ) !== 'page' || (int) get_option( 'page_on_front' ) !== $page->ID )
		) {
			return $page;
		}
	}

	public function onTheTitleFilter( $title, $pageId = null ) {
		return $this->_isFilteringSabaiPage( $pageId ) ? $this->_context->getTitle( true ) : $title;
	}

	private function _isSkipInTheLoopCheck() {
		if ( ! isset( $this->_skipInTheLoopCheck ) ) {
			$this->_skipInTheLoopCheck = false;
			if ( ! defined( 'DRTS_WORDPRESS_SKIP_IN_THE_LOOP_CHECK' ) ) {
				define( 'DRTS_WORDPRESS_SKIP_IN_THE_LOOP_CHECK', apply_filters( 'drts_wordpress_skip_in_the_loop_check', in_array( $this->_currentTheme, array( 'twenty twenty-two' ) ) ) );
			}
			if ( DRTS_WORDPRESS_SKIP_IN_THE_LOOP_CHECK ) {
				if ( is_bool( DRTS_WORDPRESS_SKIP_IN_THE_LOOP_CHECK ) ) {
					$this->_skipInTheLoopCheck = true;
				} elseif ( is_string( DRTS_WORDPRESS_SKIP_IN_THE_LOOP_CHECK ) ) {
					if ( $page_ids = explode( ',', DRTS_WORDPRESS_SKIP_IN_THE_LOOP_CHECK ) ) {
						$this->_skipInTheLoopCheck = array_map( 'intval', $page_ids );
					}
				} else {
					$this->_skipInTheLoopCheck = array( (int) DRTS_WORDPRESS_SKIP_IN_THE_LOOP_CHECK );
				}
			}
		}
		return $this->_skipInTheLoopCheck;
	}

	private function _isFilteringSabaiPage( $pageId ) {
		if ( ! $pageId = (int) $pageId ) {
			return false;
		}

		if ( is_page()
			|| is_tax()
		) {
			if ( ( ! $skipInTheLoopCheck = $this->_isSkipInTheLoopCheck() )
				|| ( is_array( $skipInTheLoopCheck ) && ! in_array( $pageId, $skipInTheLoopCheck ) )
			) {
				if ( ! in_the_loop() ) {
					return false;
				}
			}
			if ( in_array( $pageId, $this->_pageIds ) ) {
				return true;
			}

			if ( is_tax() ) {
				if ( ! defined( 'DRTS_WORDPRESS_FORCE_TAX_PAGE_TITLE' ) ) {
					define( 'DRTS_WORDPRESS_FORCE_TAX_PAGE_TITLE', apply_filters( 'drts_wordpress_force_tax_page_title', in_array( $this->_currentTheme, array( 'Newspaper', 'twenty twenty-two' ) ) ) );
				}
				// For some themes, where for some reason the title of the first post
				// in archive on taxonomy page is used as page title
				if ( DRTS_WORDPRESS_FORCE_TAX_PAGE_TITLE
					&& ! wp_get_post_parent_id( $pageId )
					&& ( $post_types = $this->_application->getComponent( 'WordPressContent' )->getPostTypeNames() )
					&& in_array( get_post_type( $pageId ), $post_types )
				) {
					return true;
				}
			}

			return false;
		}
		return isset( $GLOBALS['drts_entity'] )
			&& $GLOBALS['drts_entity']->getId() === $pageId;
	}
}
