<?php

namespace Dev4Press\Plugin\BreadcrumbsPress\Expand;

use Dev4Press\Plugin\BreadcrumbsPress\Basic\Helper;
use Dev4Press\Plugin\BreadcrumbsPress\Data\Crumb;
use Dev4Press\Plugin\BreadcrumbsPress\Data\Post;
use Dev4Press\Plugin\BreadcrumbsPress\Data\PostType;
use Dev4Press\Plugin\BreadcrumbsPress\Extend\Plugin;
use Dev4Press\Plugin\GDKOB\Front\Link;
use WP_Term;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

class GDKnowledgeBase extends Plugin {
	public static function instance() : GDKnowledgeBase {
		static $instance = null;

		if ( ! isset( $instance ) ) {
			$instance = new GDKnowledgeBase();
			$instance->run();
		}

		return $instance;
	}

	public function build( $breadcrumbs ) : array {
		if ( $this->q()->is_kob_product_sub_type_term() || $this->q()->is_kob_product_sub_type() ) {
			$breadcrumbs = $this->get_product_sub_type_archive_page();
		} else if ( $this->q()->is_kob_tax_intersection() ) {
			$breadcrumbs = $this->get_taxonomy_intersect_archive_page();
		} else if ( $this->q()->is_kob_date_intersection() ) {
			if ( $this->q()->is_year() ) {
				$breadcrumbs = $this->get_date_year_page();
			} else if ( $this->q()->is_month() ) {
				$breadcrumbs = $this->get_date_month_page();
			} else if ( $this->q()->is_day() ) {
				$breadcrumbs = $this->get_date_day_page();
			}
		} else if ( $this->q()->is_kob_author() ) {
			$breadcrumbs = $this->get_author_archive_page();
		}

		return $breadcrumbs;
	}

	/**
	 * @param array    $paths
	 * @param PostType $_type
	 * @param Post     $_post
	 * @param Crumb    $_crumb_home
	 * @param Crumb    $_crumb_post
	 * @param array    $generate
	 *
	 * @return array
	 */
	public function post_multi( $paths, $_type, $_post, $_crumb_home, $_crumb_post, $generate ) : array {
		if ( $_type->is_knowledge() ) {
			if ( $generate['author'] ) {
				$paths['kob_author']     = $this->get_path_cpt_author( $_type, $_post, $_crumb_home, $_crumb_post, false );
				$paths['kob_cpt_author'] = $this->get_path_cpt_author( $_type, $_post, $_crumb_home, $_crumb_post );
			}

			if ( $generate['date'] ) {
				$paths['kob_day']   = $this->get_path_cpt_day( $_type, $_post, $_crumb_home, $_crumb_post );
				$paths['kob_month'] = $this->get_path_cpt_month( $_type, $_post, $_crumb_home, $_crumb_post );
				$paths['kob_year']  = $this->get_path_cpt_year( $_type, $_post, $_crumb_home, $_crumb_post );
			}

			if ( $generate['terms'] ) {
				foreach ( $_type->get_taxonomies_names() as $tax ) {
					$_terms = $_post->get_terms( $tax );

					foreach ( $_terms as $term ) {
						$_key           = 'kob_taxonomy_' . $tax . '_' . $term->term_id;
						$paths[ $_key ] = array(
							'home'                   => $_crumb_home,
							'post_type_archive'      => $this->c()->crumbs_post_type_archive( $_type ),
							'term_' . $term->term_id => $this->crumbs_term( $term, $_post ),
							'post'                   => $_crumb_post,
						);
					}
				}
			}
		}

		return $paths;
	}

	/**
	 * @param PostType $_type
	 * @param Post     $_post
	 * @param Crumb    $_crumb_home
	 * @param Crumb    $_crumb_post
	 * @param string   $path
	 * @param string   $taxonomy
	 *
	 * @return Crumb[]
	 */
	public function post_single( $_type, $_post, $_crumb_home, $_crumb_post, $path, $taxonomy ) : array {
		$crumbs = array();

		switch ( $path ) {
			case 'kob_author':
				if ( $_type->has_kob_author() ) {
					$crumbs = $this->get_path_cpt_author( $_type, $_post, $_crumb_home, $_crumb_post );
				}
				break;
			case 'kob_day':
				if ( $_type->has_kob_day() ) {
					$crumbs = $this->get_path_cpt_day( $_type, $_post, $_crumb_home, $_crumb_post );
				}
				break;
			case 'kob_month':
				if ( $_type->has_kob_month() ) {
					$crumbs = $this->get_path_cpt_month( $_type, $_post, $_crumb_home, $_crumb_post );
				}
				break;
			case 'kob_year':
				if ( $_type->has_kob_year() ) {
					$crumbs = $this->get_path_cpt_year( $_type, $_post, $_crumb_home, $_crumb_post );
				}
				break;
			case 'kob_intersection':
				if ( $_type->has_kob_intersection() && $_type->is_taxonomy_valid( $taxonomy ) ) {
					$term = $_post->get_first_term( $taxonomy );

					if ( $term !== false ) {
						$chain = Helper::instance()->chain_terms( $term->term_id, $taxonomy );
						$chain = array_reverse( $chain );

						$crumbs = array(
							'home'              => $_crumb_home,
							'post_type_archive' => $this->c()->crumbs_post_type_archive( $_type ),
						);

						for ( $i = 0; $i < count( $chain ); $i ++ ) {
							$crumbs[ 'term_' . $chain[ $i ]->term_id ] = $this->crumbs_term( $chain[ $i ], $_post );
						}

						$crumbs['post'] = $_crumb_post;
					}
				}
				break;
		}

		return $crumbs;
	}

	/**
	 * @param null|string  $post_type
	 * @param null|WP_Term $term
	 *
	 * @return Crumb[]
	 */
	public function get_taxonomy_intersect_archive_page( $post_type = null, $term = null ) : array {
		$post_type = is_null( $post_type ) ? $this->q()->get_post_type() : $post_type;
		$term      = is_null( $term ) ? get_term( $this->q()->get_term_id(), $this->q()->get_taxonomy() ) : $term;
		$_post     = PostType::instance( $post_type );

		return array(
			'home'  => $this->b()->home(),
			'posts' => $this->c()->crumbs_post_type_archive( $_post ),
			'term'  => $this->b()->crumb( array(
				'type'  => 'term',
				'title' => $term->name,
				'url'   => Link::instance()->intersect( $post_type, $term, $term->taxonomy ),
				'id'    => $term->term_id,
			) ),
		);
	}

	/**
	 * @param null|string  $sub_post_type
	 * @param null|WP_Term $term
	 *
	 * @return Crumb[]
	 */
	public function get_product_sub_type_archive_page( $sub_post_type = null, $term = null ) : array {
		$sub_post_type = is_null( $sub_post_type ) ? $this->q()->get_kob_sub_type() : $sub_post_type;

		if ( is_null( $term ) && $this->q()->is_kob_product_sub_type_term() ) {
			$term = get_term( $this->q()->get_kob_term_id(), $this->q()->get_kob_taxonomy() );
		}

		$type_product = PostType::instance( gdkob()->post_type_product() );
		$post_type    = PostType::instance( $sub_post_type );
		$post         = Post::instance( $this->q()->get_post_id() );

		$crumbs = array(
			'home'  => $this->b()->home(),
			'posts' => $this->c()->crumbs_post_type_archive( $type_product ),
			'post'  => $this->c()->crumbs_post( $post, false ),
			'type'  => $this->b()->crumb( array(
				'type'    => 'post_type',
				'title'   => $post_type->get_label(),
				'url'     => Link::instance()->product( $this->q()->get_post_id(), $sub_post_type ),
				'current' => is_null( $term ),
			) ),
		);

		if ( ! is_null( $term ) ) {
			$crumbs[] = $this->b()->crumb( array(
				'type'    => 'term',
				'title'   => $term->name,
				'url'     => Link::instance()->product( $this->q()->get_post_id(), $sub_post_type, $term, $term->taxonomy ),
				'current' => true,
			) );
		}

		return $crumbs;
	}

	/**
	 * @param null|string $post_type
	 * @param null|int    $year
	 * @param bool        $current
	 *
	 * @return Crumb[]
	 */
	public function get_date_year_page( $post_type = null, $year = null, $current = true ) : array {
		$post_type = is_null( $post_type ) ? $this->q()->get_post_type() : $post_type;
		$year      = is_null( $year ) ? $this->q()->get_year() : intval( $year );

		return array(
			'home'      => $this->b()->home(),
			'posts'     => $this->b()->post_type_archive( $post_type, false ),
			'date-year' => $this->b()->crumb( array(
				'type'    => 'date-year',
				'title'   => $current ? $this->b()->title( 'core_date_archives', $year ) : $year,
				'display' => $current ? $this->b()->display( 'core_date_archives' ) : '%title%',
				'url'     => Link::instance()->date_archive( $post_type, $year ),
				'current' => $current,
			) ),
		);
	}

	/**
	 * @param null|string $post_type
	 * @param null|int    $year
	 * @param null|int    $month
	 * @param bool        $use_template
	 *
	 * @return Crumb[]
	 */
	public function get_date_month_page( $post_type = null, $year = null, $month = null, $use_template = true ) : array {
		$post_type = is_null( $post_type ) ? $this->q()->get_post_type() : $post_type;
		$year      = is_null( $year ) ? $this->q()->get_year() : intval( $year );
		$month     = is_null( $month ) ? $this->q()->get_month() : absint( $month );

		$month = $month < 1 || $month > 12 ? 1 : $month;
		$value = Helper::instance()->month_title( $year, $month );

		$breadcrumbs = $this->get_date_year_page( $post_type, $year, false );
		$breadcrumbs['date-year']->set_current( false );
		$breadcrumbs['date-month'] = $this->b()->crumb( array(
			'type'    => 'date-month',
			'title'   => $use_template ? $this->b()->title( 'core_date_archives', $value ) : str_pad( $month, 2, '0', STR_PAD_LEFT ),
			'display' => $use_template ? $this->b()->display( 'core_date_archives' ) : '%title%',
			'url'     => Link::instance()->date_archive( $post_type, $year, $month ),
			'current' => true,
		) );

		return $breadcrumbs;
	}

	/**
	 * @param null|string $post_type
	 * @param null|int    $year
	 * @param null|int    $month
	 * @param null|int    $day
	 * @param bool        $use_template
	 *
	 * @return Crumb[]
	 */
	public function get_date_day_page( $post_type = null, $year = null, $month = null, $day = null, $use_template = true ) : array {
		$post_type = is_null( $post_type ) ? $this->q()->get_post_type() : $post_type;
		$year      = is_null( $year ) ? $this->q()->get_year() : intval( $year );
		$month     = is_null( $month ) ? $this->q()->get_month() : absint( $month );
		$day       = is_null( $day ) ? $this->q()->get_day() : absint( $day );

		$month = $month < 1 || $month > 12 ? 1 : $month;
		$day   = $day < 1 || $day > 31 ? 1 : $day;

		$value = Helper::instance()->day_title( $year, $month, $day );

		$breadcrumbs = $this->get_date_month_page( $post_type, $year, $month, false );
		$breadcrumbs['date-month']->set_current( false );
		$breadcrumbs['date-day'] = $this->b()->crumb( array(
			'type'    => 'date-day',
			'title'   => $use_template ? $this->b()->title( 'core_date_archives', $value ) : str_pad( $day, 2, '0', STR_PAD_LEFT ),
			'display' => $use_template ? $this->b()->display( 'core_date_archives' ) : '%title%',
			'url'     => Link::instance()->date_archive( $post_type, $year, $month, $day ),
			'current' => true,
		) );

		return $breadcrumbs;
	}

	/**
	 * @param null|string $post_type
	 * @param null|int    $author
	 * @param bool        $use_template
	 *
	 * @return Crumb[]
	 */
	public function get_author_archive_page( $post_type = null, $author = null, $use_template = true ) : array {
		$author = is_null( $author ) ? $this->q()->get_author() : absint( $author );

		$value = Helper::instance()->user_title( $author );

		return array(
			'home'   => $this->b()->home(),
			'author' => $this->b()->crumb( array(
				'type'    => 'author',
				'title'   => $use_template ? $this->b()->title( 'core_author_archives', $value ) : $value,
				'display' => $use_template ? $this->b()->display( 'core_author_archives' ) : '%title%',
				'url'     => Link::instance()->author_archive( $author ),
				'current' => true,
			) ),
		);
	}

	/**
	 * @param PostType $_type
	 * @param Post     $_post
	 * @param Crumb    $_crumb_home
	 * @param Crumb    $_crumb_post
	 *
	 * @return Crumb[]
	 */
	public function get_path_cpt_author( $_type, $_post, $_crumb_home, $_crumb_post, $_with_post_type = true ) : array {
		$crumbs = array( 'home' => $_crumb_home );

		if ( $_with_post_type ) {
			$crumbs['post_type_archive'] = $this->c()->crumbs_post_type_archive( $_type );
		}

		$crumbs['author'] = $this->crumbs_post_author( $_post );
		$crumbs['post']   = $_crumb_post;

		return $crumbs;
	}

	/**
	 * @param PostType $_type
	 * @param Post     $_post
	 * @param Crumb    $_crumb_home
	 * @param Crumb    $_crumb_post
	 *
	 * @return Crumb[]
	 */
	public function get_path_cpt_day( $_type, $_post, $_crumb_home, $_crumb_post ) : array {
		return array(
			'home'              => $_crumb_home,
			'post_type_archive' => $this->c()->crumbs_post_type_archive( $_type ),
			'year'              => $this->crumbs_year( $_post ),
			'month'             => $this->crumbs_month( $_post ),
			'day'               => $this->crumbs_day( $_post ),
			'post'              => $_crumb_post,
		);
	}

	/**
	 * @param PostType $_type
	 * @param Post     $_post
	 * @param Crumb    $_crumb_home
	 * @param Crumb    $_crumb_post
	 *
	 * @return Crumb[]
	 */
	public function get_path_cpt_month( $_type, $_post, $_crumb_home, $_crumb_post ) : array {
		return array(
			'home'              => $_crumb_home,
			'post_type_archive' => $this->c()->crumbs_post_type_archive( $_type ),
			'year'              => $this->crumbs_year( $_post ),
			'month'             => $this->crumbs_month( $_post ),
			'post'              => $_crumb_post,
		);
	}

	/**
	 * @param PostType $_type
	 * @param Post     $_post
	 * @param Crumb    $_crumb_home
	 * @param Crumb    $_crumb_post
	 *
	 * @return Crumb[]
	 */
	public function get_path_cpt_year( $_type, $_post, $_crumb_home, $_crumb_post ) : array {
		return array(
			'home'              => $_crumb_home,
			'post_type_archive' => $this->c()->crumbs_post_type_archive( $_type ),
			'year'              => $this->crumbs_year( $_post ),
			'post'              => $_crumb_post,
		);
	}

	public function crumbs_term( WP_Term $term, Post $post ) : Crumb {
		return $this->b()->crumb( array(
			'type'  => 'term',
			'title' => $term->name,
			'url'   => Link::instance()->intersect( $post->get_post_type(), $term, $term->taxonomy ),
			'id'    => $term->term_id,
		) );
	}

	public function crumbs_post_author( Post $post ) : Crumb {
		return $this->b()->crumb( array(
			'type'  => 'post',
			'title' => $post->author_display(),
			'url'   => $post->author_url(),
		) );
	}

	public function crumbs_year( Post $post ) : Crumb {
		return $this->b()->crumb( array(
			'type'  => 'year',
			'title' => $post->get_year_formatted(),
			'url'   => Link::instance()->date_archive( $post->get_post_type(), $post->get_year() ),
		) );
	}

	public function crumbs_month( Post $post ) : Crumb {
		return $this->b()->crumb( array(
			'type'  => 'month',
			'title' => $post->get_month_formatted(),
			'url'   => Link::instance()->date_archive( $post->get_post_type(), $post->get_year(), $post->get_month() ),
		) );
	}

	public function crumbs_day( Post $post ) : Crumb {
		return $this->b()->crumb( array(
			'type'  => 'day',
			'title' => $post->get_day_formatted(),
			'url'   => Link::instance()->date_archive( $post->get_post_type(), $post->get_year(), $post->get_month(), $post->get_day() ),
		) );
	}

	public function complete( $breadcrumbs ) : array {
		return $breadcrumbs;
	}

	public function ready() {

	}
}
