<?php

namespace Dev4Press\Plugin\BreadcrumbsPress\Data;

use Dev4Press\Plugin\BreadcrumbsPress\Expand\bbPress;
use WP_Post_Type;

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

/**
 * @method bool has_posts()
 * @method bool has_archive()
 * @method bool has_year()
 * @method bool has_month()
 * @method bool has_day()
 * @method bool has_author()
 * @method bool has_terms()
 * @method bool has_hierarchy()
 * @method bool has_parent_post()
 * @method bool has_kob_year()
 * @method bool has_kob_month()
 * @method bool has_kob_day()
 * @method bool has_kob_author()
 * @method bool has_kob_product()
 * @method bool has_kob_intersection()
 * @method bool has_cpt_year()
 * @method bool has_cpt_month()
 * @method bool has_cpt_day()
 * @method bool has_cpt_author()
 * @method bool has_cpt_intersection()
 * @method string get_path()
 * @method string get_hierarchy()
 * @method string get_taxonomy()
 * @method string get_term_index()
 * @method bool get_with_posts()
 * @method bool get_expand_cpt()
 * @method bool get_expand_kob()
 */
final class PostType {
	/** @var string */
	private $name;
	/** @var WP_Post_Type|null */
	private $object;
	/** @var \WP_Taxonomy[] */
	private $taxonomies;
	/** @var array */
	private $taxonomies_list;
	/** @var bool */
	private $knowledge = false;
	/** @var bool */
	private $knowledge_product = false;
	/** @var bool */
	private $bbpress = false;
	/** @var bool */
	private $woocommerce = false;

	private $rules = array(
		'path'       => '',
		'hierarchy'  => '',
		'taxonomy'   => '',
		'term_index' => '',
		'with_posts' => false,
		'expand_cpt' => false,
		'expand_kob' => false,
	);

	private $data = array(
		'posts'            => false,
		'archive'          => false,
		'year'             => false,
		'month'            => false,
		'day'              => false,
		'author'           => false,
		'terms'            => false,
		'hierarchy'        => false,
		'parent_post'      => false,
		'kob_year'         => false,
		'kob_month'        => false,
		'kob_day'          => false,
		'kob_author'       => false,
		'kob_intersection' => false,
		'kob_product'      => false,
		'cpt_year'         => false,
		'cpt_month'        => false,
		'cpt_day'          => false,
		'cpt_author'       => false,
		'cpt_intersection' => false,
	);

	public function __construct( $post_type ) {
		$this->name   = $post_type;
		$this->object = get_post_type_object( $post_type );

		if ( $this->object ) {
			$taxonomies = get_object_taxonomies( $post_type, 'objects' );

			foreach ( $taxonomies as $taxonomy ) {
				if ( $taxonomy->public && $taxonomy->name != 'post_format' && $taxonomy->rewrite !== false ) {
					$this->taxonomies[ $taxonomy->name ]      = $taxonomy;
					$this->taxonomies_list[ $taxonomy->name ] = $taxonomy->label . ' (' . $taxonomy->name . ')';
				}
			}

			$this->data['terms'] = ! empty( $this->taxonomies );

			$this->data['archive']   = $this->object->has_archive !== false;
			$this->data['hierarchy'] = $this->object->hierarchical;

			if ( $post_type === 'post' ) {
				$this->data['posts']  = true;
				$this->data['year']   = true;
				$this->data['month']  = true;
				$this->data['day']    = true;
				$this->data['author'] = true;
			}

			if ( $post_type === 'attachment' ) {
				$this->data['parent_post'] = true;
			}

			if ( breadcrumbspress()->has_gd_knowledge_base() ) {
				$this->knowledge         = gdkob()->is_valid_post_type( $this->name );
				$this->knowledge_product = $this->name === gdkob()->post_type_product();
			}

			if ( breadcrumbspress()->has_bbpress() ) {
				$this->bbpress = in_array( $post_type, bbPress::instance()->get_post_types() );
			}

			if ( breadcrumbspress()->has_woocommerce() ) {
				$this->woocommerce = $post_type === 'product';
			}

			add_action( 'breadcrumbspress_plugin_core_ready', array( $this, 'update' ) );
		}
	}

	public static function instance( $post_type ) : PostType {
		static $instance = array();

		if ( ! isset( $instance[ $post_type ] ) ) {
			$instance[ $post_type ] = new PostType( $post_type );
		}

		return $instance[ $post_type ];
	}

	public function __call( $name, $arguments ) {
		$name = strtolower( $name );

		if ( substr( $name, 0, 4 ) == 'has_' ) {
			$condition = substr( $name, 4 );

			if ( isset( $this->data[ $condition ] ) ) {
				return (bool) $this->data[ $condition ];
			}

			return false;
		} else if ( substr( $name, 0, 4 ) == 'get_' ) {
			$condition = substr( $name, 4 );

			if ( isset( $this->rules[ $condition ] ) ) {
				return $this->rules[ $condition ];
			}

			return '';
		}

		return false;
	}

	public function update() {
		$this->rules['path']       = breadcrumbspress_settings()->get( 'cpt_' . $this->name, 'path' );
		$this->rules['hierarchy']  = breadcrumbspress_settings()->get( 'cpt_hierarchy_' . $this->name, 'rules' );
		$this->rules['taxonomy']   = breadcrumbspress_settings()->get( 'cpt_taxonomy_' . $this->name, 'rules' );
		$this->rules['term_index'] = breadcrumbspress_settings()->get( 'cpt_term_index_' . $this->name, 'rules' );
		$this->rules['with_posts'] = breadcrumbspress_settings()->get( 'cpt_with_posts_' . $this->name, 'rules' );

		if ( ! $this->has_hierarchy() ) {
			$this->rules['hierarchy'] = 'no';
		}

		if ( substr( $this->rules['path'], 0, 4 ) === 'cpt_' ) {
			$this->rules['expand_cpt'] = true;
		}

		if ( substr( $this->rules['path'], 0, 4 ) === 'kob_' ) {
			$this->rules['expand_kob'] = true;
		}

		if ( breadcrumbspress()->allowed_for_posts_page( $this->name ) ) {
			$this->data['posts'] = true;
		}

		if ( $this->data['archive'] ) {
			if ( $this->is_knowledge() ) {
				if ( ! $this->is_knowledge_product() ) {
					$this->data['kob_year']    = true;
					$this->data['kob_month']   = true;
					$this->data['kob_day']     = true;
					$this->data['kob_product'] = true;
				}

				$this->data['kob_author']       = true;
				$this->data['kob_intersection'] = true;
			} else if ( breadcrumbspress()->has_gd_content_tools() ) {
				if ( gdcet_has_post_type_date_archives( $this->name ) ) {
					$this->data['cpt_year']  = gdcet_has_post_type_date_archives( $this->name, 'year' );
					$this->data['cpt_month'] = gdcet_has_post_type_date_archives( $this->name, 'month' );
					$this->data['cpt_day']   = gdcet_has_post_type_date_archives( $this->name, 'day' );
				}

				if ( gdcet_has_post_type_author_archives( $this->name ) ) {
					$this->data['cpt_author'] = true;
				}

				if ( ! empty( $this->taxonomies ) && gdcet_has_post_type_intersections( $this->name, 'simple' ) ) {
					$this->data['cpt_intersection'] = true;
				}
			}
		}
	}

	public function get_name() : string {
		return $this->name;
	}

	public function get_label() : string {
		return $this->object->label;
	}

	public function get_object() : WP_Post_Type {
		return $this->object;
	}

	public function get_taxonomies() : array {
		return $this->taxonomies;
	}

	public function get_first_taxonomy_name() : string {
		$names = $this->get_taxonomies_names();

		return empty( $names ) ? '' : $names[0];
	}

	public function get_taxonomies_list() : array {
		return $this->taxonomies_list;
	}

	public function get_taxonomies_names() : array {
		return empty( $this->taxonomies_list ) ? array() : array_keys( $this->taxonomies_list );
	}

	public function is_taxonomy_valid( $taxonomy ) : bool {
		return isset( $this->taxonomies_list[ $taxonomy ] );
	}

	public function is_knowledge() : bool {
		return $this->knowledge;
	}

	public function is_knowledge_product() : bool {
		return $this->knowledge_product;
	}

	public function is_bbpress() : bool {
		return $this->bbpress;
	}

	public function is_woocommerce() : bool {
		return $this->woocommerce;
	}
}
