<?php
namespace TotalThemeCore\Cards;

use WP_Query;
use WPEX_Meta_Factory;
use WPEX_Card;

defined( 'ABSPATH' ) || exit;

/**
 * Card Builder.
 *
 * @package TotalThemeCore
 * @version 1.4.6
 */
final class Builder {

	/**
	 * Card builder post type name.
	 */
	const POST_TYPE = 'wpex_card';

	/**
	 * Check if front-end editing is allowed.
	 */
	const ALLOW_VC_FRONTEND = true;

	/**
	 * Check if vc has initialized.
	 */
	protected $vc_init = false;

	/**
	 * Stores array of custom cards IDs.
	 */
	protected static $custom_cards;

	/**
	 * Instance.
	 */
	private static $instance;

	/**
	 * Create or retrieve the class instance.
	 */
	public static function instance() {
		if ( is_null( static::$instance ) ) {
			static::$instance = new self();
			static::$instance->init_hooks();
		}

		return static::$instance;
	}

	/**
	 * Get things started.
	 */
	public function init_hooks() {
		if ( ! get_theme_mod( 'card_builder_enable', true ) || ! defined( 'TOTAL_THEME_ACTIVE' ) ) {
			return;
		}

		if ( is_admin() ) {
			add_action( 'admin_init', [ $this, 'admin_init' ] );
		}

		add_action( 'init', [ $this, 'register_post_type' ] );
		add_filter( 'wpex_card_styles', [ $this, 'filter_card_styles' ] );

		if ( defined( 'WPEX_VC_ACTIVE' ) && WPEX_VC_ACTIVE ) {
			add_action( 'init', [ $this, 'vc_init' ], 8 );
			add_action( 'init', [ $this, 'vc_print_scripts' ], 11 );
		}
	}

	/**
	 * Admin init.
	 */
	public function admin_init() {
		add_action( 'admin_head-post.php', [ $this, 'add_back_button' ] );

		if ( class_exists( 'WPEX_Meta_Factory' ) ) {
			new WPEX_Meta_Factory( $this->metabox() );
		}

		if ( defined( 'WPEX_VC_ACTIVE' ) && WPEX_VC_ACTIVE ) {
			if ( ! self::ALLOW_VC_FRONTEND ) {
				add_filter( 'vc_show_button_fe', [ $this, 'disable_vc_button_fe' ], 10, 3 );
				add_action( 'admin_head', [ $this, 'disable_vc_frontend_editor' ] );
			}
		}
	}

	/**
	 * Returns array of cards.
	 */
	public static function get_custom_cards() {
		if ( ! is_null( self::$custom_cards ) ) {
			return self::$custom_cards;
		}

		if ( ! post_type_exists( self::POST_TYPE ) ) {
			return [];
		}

		$custom_cards = new WP_Query( [
			'posts_per_page'   => '-1',
			'orderby'          => 'date',
			'order'            => 'ASC',
			'numberposts'      => 200,
			'post_type'        => self::POST_TYPE,
			'post_status'      => 'publish',
			'fields'           => 'ids',
			'suppress_filters' => true, // do not show translated items in WPML.
		] );

		if ( $custom_cards && $custom_cards instanceof WP_Query ) {
			self::$custom_cards = $custom_cards->posts;
			return self::$custom_cards;
		}
	}

	/**
	 * Returns parent menu.
	 */
	public function get_parent_menu() {
		return defined( 'WPEX_THEME_PANEL_SLUG' ) ? WPEX_THEME_PANEL_SLUG : 'themes.php';
	}

	/**
	 * Add a back button to the Font Manager main page.
	 */
	public function add_back_button() {
		global $current_screen;

		if ( ! empty( $current_screen->post_type ) && self::POST_TYPE !== $current_screen->post_type ) {
			return;
		}

		wp_enqueue_script( 'jQuery' );

		?>

		<script>
			jQuery( function() {
				jQuery( 'body.post-type-<?php echo sanitize_html_class( self::POST_TYPE ); ?> .wrap h1' ).append( '<a href="<?php echo esc_url( admin_url( 'edit.php?post_type=' . self::POST_TYPE ) ); ?>" class="page-title-action" style="margin-left:20px"><?php esc_html_e( 'All Custom Cards', 'total-theme-core' ); ?></a> <a href="https://total.wpexplorer.com/features/cards/" class="page-title-action" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'View Preset Cards', 'total-theme-core' ); ?></a>' );
			} );
		</script>

		<?php
	}

	/**
	 * Register post type.
	 */
	public function register_post_type() {
		$args = [
			'labels' => [
				'name' => esc_html__( 'Custom Cards', 'total-theme-core' ),
				'singular_name' => esc_html__( 'Card', 'total-theme-core' ),
				'add_new' => esc_html__( 'Add New Card' , 'total-theme-core' ),
				'add_new_item' => esc_html__( 'Add New Card' , 'total-theme-core' ),
				'edit_item' => esc_html__( 'Edit Card' , 'total-theme-core' ),
				'new_item' => esc_html__( 'New Card' , 'total-theme-core' ),
				'view_item' => esc_html__( 'View Card', 'total-theme-core' ),
				'search_items' => esc_html__( 'Search Cards', 'total-theme-core' ),
				'not_found' => esc_html__( 'No Cards found', 'total-theme-core' ),
				'not_found_in_trash' => esc_html__( 'No Cards found in Trash', 'total-theme-core' ),
			],
			'public' => false,
			'has_archive' => false,
			'query_var' => true,
			'_builtin' => false,
			'show_ui' => true,
			'show_in_rest' => true, // disable Gutenberg.
			'show_in_menu' => $this->get_parent_menu(),
			'show_in_nav_menus' => false,
			'show_in_admin_bar' => false,
			'exclude_from_search' => false,
			'publicly_queryable' => false,
			'capability_type' => 'page',
			'hierarchical' => false,
			'menu_position' => null,
			'rewrite' => false,
			'supports' => [
				'title',
				'editor',
			],
			'menu_position' => null,
		];

		if ( $this->is_elementor_preview_mode() || ( self::ALLOW_VC_FRONTEND && $this->is_vc_front_end_editor() ) ) {
			$args['public']             = true;
			$args['publicly_queryable'] = true;
		}

		register_post_type( self::POST_TYPE, $args );

		// Add Elementor support.
		add_post_type_support( self::POST_TYPE, 'elementor' );
	}

	/**
	 * Check if we are currently editing a card in frontend editor mode.
	 */
	protected function is_vc_front_end_editor() {
		if ( function_exists( 'vc_get_param' )
			&& 'true' === vc_get_param( 'vc_editable' )
			&& self::POST_TYPE === get_post_type( vc_get_param( 'vc_post_id' ) )
		) {
			return true;
		}
		return false;
	}

	/**
	 * Check if we are currently editing via the elementor front-end editor.
	 */
	public function is_elementor_preview_mode() {
		if ( defined( 'WPEX_ELEMENTOR_ACTIVE' )
			&& WPEX_ELEMENTOR_ACTIVE
			&& isset( $_GET['elementor-preview'] )
			&& isset( $_GET['wpex_card'] )
		) {
			return true;
		}
		return false;
	}

	/**
	 * Disables the WPBakery "Edit with WPBakery" hover link in the WP admin.
	 */
	public function disable_vc_button_fe( $check, $post_id, $post_type ) {
		if ( self::POST_TYPE === $post_type ) {
			$check = false;
		}
		return $check;
	}

	/**
	 * Disables the WPBakery front-end button.
	 */
	public function disable_vc_frontend_editor() {
		global $current_screen;
		if ( ! empty( $current_screen->post_type )
			&& self::POST_TYPE === $current_screen->post_type
			&& function_exists( 'vc_disable_frontend' )
		) {
			vc_disable_frontend();
		}
	}

	/**
	 * Makes sure that you can edit wpex_cards with WPBakery even though it's a private type.
	 */
	public function vc_get_post_type() {
			$post_type = get_post_type();
			if ( empty( $post_type ) ) {
				if ( vc_get_param( 'post' ) ) {
					$post_type = get_post_type( (int) vc_get_param( 'post' ) );
				} elseif ( vc_get_param( 'post_type' ) ) {
					$post_type = vc_get_param( 'post_type' );
				}
			}
			return $post_type;
		}

	/**
	 * Makes sure that you can edit wpex_cards with WPBakery even though it's a private type.
	 */
	public function vc_init() {
		if ( $this->vc_init ) {
			return;
		}

		if ( self::POST_TYPE === $this->vc_get_post_type() ) {
			add_filter( 'vc_role_access_with_post_types_get_state', '__return_true' );
			add_filter( 'vc_role_access_with_backend_editor_get_state', '__return_true' );
			add_filter( 'vc_role_access_with_frontend_editor_get_state', '__return_true' );
			add_filter( 'vc_check_post_type_validation', '__return_true' );
			add_filter( 'vc_is_valid_post_type_be', '__return_true' );
			add_filter( 'vc_is_valid_post_type_fe', '__return_false' );
		}

		$this->vc_init = true;
	}

	/**
	 * Hooks into various places to print CSS for hiding vc elements.
	 */
	public function vc_print_scripts() {
		if ( function_exists( 'vc_is_page_editable' ) && vc_is_page_editable() ) {
			add_action( 'wp_head', [ $this, 'vc_hide_elements_css' ] ); // @todo where these icons are used in iframe?
		} elseif ( is_admin() ) {
			add_action( 'admin_print_scripts-post.php', [ $this, 'vc_hide_elements_css' ], 1 );
			add_action( 'admin_print_scripts-post-new.php', [ $this, 'vc_hide_elements_css' ], 1 );
		}
	}

	/**
	 * Disables certain elements so they can't be used when building cards.
	 */
	public function vc_hide_elements_css() {
		if ( self::POST_TYPE !== $this->vc_get_post_type() ) {
			return;
		}
		$not_list = '';
		$shortcodes_whitelist = [
			// VC
			'vc_row',
		//  'vc_row_inner',
			'vc_column',
		//  'vc_column_inner',
			'vc_column_text',

			// Total
			'vcex_flex_container',
			'vcex_grid_container',
			'vcex_heading',
			'vcex_image',
			'vcex_image_grid',
			'vcex_image_swap',
			'vcex_button',
			'vcex_divider',
			'vcex_spacing',
			'vcex_custom_field',
			'vcex_image_ba',
			'vcex_font_icon',
			'vcex_shortcode',
			'vcex_skillbar',
			'vcex_divider_dots',
			'vcex_divider_multicolor',
			'vcex_social_share',
			'vcex_author_bio',

			// Post based,
			'vcex_post_meta',
			'vcex_post_content',
			'vcex_post_excerpt',
			'vcex_page_title',
			'vcex_post_media',
			'vcex_post_terms',
		];
		foreach ( $shortcodes_whitelist as $shortcode ) {
			$not_list .= ':not([data-element="' . esc_attr( $shortcode ) . '"])';
		}
		echo '<style>#vc_post-settings-button,.vc_ui-add-element-header-container > .vc_ui-panel-header > .vc_ui-panel-header-content,.wpb-layout-element-button' . $not_list .'{display:none!important;}</style>';
		return;
		if ( ! is_callable( [ 'WPBMap', 'getAllShortCodes' ] ) ) {
			return;
		}
	}

	/**
	 * Adds the custom cards to the cards list.
	 */
	public function filter_card_styles( $styles ) {
		$custom_cards = self::get_custom_cards();

		if ( is_array( $custom_cards ) ) {
			foreach ( $custom_cards as $card_id ) {
				$card_name = the_title_attribute( [
					'echo' => false,
					'post' => get_post( $card_id ),
				] );
				if ( $card_name ) {
					$card_name = sprintf( esc_attr__( 'Custom Card: %1$s', 'total-theme-core' ), $card_name );
					$styles['template_' . $card_id] = [
						'name' => $card_name,
					];
				}
			}
		}

		return $styles;
	}

	/**
	 * Adds cards meta options.
	 */
	public function metabox() {
		if ( self::ALLOW_VC_FRONTEND && defined( 'WPEX_VC_ACTIVE' ) && WPEX_VC_ACTIVE ) {
			$fields = [
				[
					'name' => esc_html__( 'Frontend Editor Width', 'total-theme-core' ),
					'id'   => 'preview_width',
					'type' => 'text',
					'desc' => esc_html__( 'Enter a custom width to contain your card while editing in front-end mode. Leave empty to use the default site width.', 'total-theme-core' ),
				],
			];
		}

		$fields[] = [
			'name' => esc_html__( 'Extra class name', 'total-theme-core' ),
			'id'   => 'el_class',
			'type' => 'text',
			'desc' => esc_html__( 'Add extra classes to the card element.', 'total-theme-core' ),
		];

		if ( is_callable( [ 'WPEX_Card', 'get_link_types' ] ) ) {
			$fields[] = [
				'name'    => esc_html__( 'Link Type', 'total-theme-core' ),
				'id'      => 'link_type',
				'type'    => 'select',
				'choices' =>  WPEX_Card::get_link_types(),
				'desc'    => esc_html__( 'By default custom cards will have a link around the entire card so any links inside the card will be stripped out. Select the "none" link type if you wish to add your own links within the card.', 'total-theme-core' ),
			];
		}

		return [
			'id'       => 'wpex-card',
			'title'    => esc_html__( 'Card Settings', 'total-theme-core' ),
			'screen'   => [ self::POST_TYPE ],
			'context'  => 'side',
			'priority' => 'default',
			'fields'   => $fields,
		];
	}

}