<?php
/**
 * JetEngine compatibility package Query Builder manager.
 *
 * @package JET_ABAF\Compatibility\Packages\Jet_Engine\Query_Builder
 */

namespace JET_APB\Compatibility\Packages\Jet_Engine\Query_Builder;

use \Jet_Engine\Query_Builder\Query_Editor;
use \JET_APB\Compatibility\Packages\Jet_Engine;
use JET_APB\Plugin;

class Manager {

	/**
	 * A reference to an instance of this class.
	 *
	 * @var object
	 */
	private static $instance = null;

	/**
	 * Query builder component slug.
	 *
	 * @var string
	 */
	public $slug = 'jet-appointment-query';

	public $appointment_model_object = '\JET_APB\Resources\Appointment_Model';

	/**
	 * Prefix for appointment listing fields/meta keys.
	 *
	 * @var string
	 */
	public $appointment_fields_prefix = 'jet_apb_list__';

	public function __construct() {

		add_action( 'jet-engine/query-builder/query-editor/register', [ $this, 'register_editor_component' ] );
		add_action( 'jet-engine/query-builder/queries/register', [ $this, 'register_query' ] );

		add_filter( 'jet-engine/query-builder/types/sql-query/cast-objects', [ $this, 'add_booking_to_cast' ] );

		/**
		 * Fix `cx-vui-f-select` component with `jet-query-dynamic-args`. This is temporary solution until vue-ui module fix this.
		 */
		add_action('admin_head', function () {

			$screen = get_current_screen();

			if ( 'jetengine_page_jet-engine-query' === $screen->id ) {
				echo '<style>
						.cx-vui-component.cx-vui-component--has-macros .cx-vui-f-select {
							width: 100%;
						}
				</style>';
			}

		} );

        add_filter( 'jet-engine/listing/custom-post-id', [ $this, 'get_appointment_id' ], 10, 2 );
        add_filter( 'jet-engine/listings/data/prop-not-found', [ $this, 'get_appointment_prop' ], 10, 3 );
        add_filter( 'jet-engine/listings/data/get-meta/query', [ $this, 'get_appointment_meta' ], 10, 3 );

	}

	/**
	 * Register editor components.
	 *
	 * Register editor component for the query builder
	 *
	 * @access public
	 *
	 * @param Query_Editor $manager Query editor instance.
	 *
	 * @return void
	 */
	public function register_editor_component( $manager ) {
		require_once Jet_Engine::instance()->package_path( 'query-builder/editor.php' );
		$manager->register_type( new Editor() );
	}

	/**
	 * Register query class
	 *
	 * @param  $manager
	 *
	 * @return void
	 */
	public function register_query( $manager ) {
		require_once Jet_Engine::instance()->package_path( 'query-builder/query.php' );
		$manager::register_query( $this->slug, __NAMESPACE__ . '\Query' );
	}

	/**
	 * Add appointment to cast.
	 *
	 * Add appointment object to cast objects.
	 *
	 * @access public
	 *
	 * @param array $objects List of cast objects.
	 *
	 * @return array
	 */
	public function add_booking_to_cast( $objects ) {

		$objects[ $this->appointment_model_object ] = __( 'Appointment', 'jet-appointments-booking' );

		return $objects;

	}

	/**
	 * Set correct appointment id after `Jet Appointments Booking Query` for post loop output.
	 *
	 * @param $id
	 * @param $object
	 *
	 * @return mixed
	 */
    public function get_appointment_id( $id, $object ) {

        if ( $object && is_object( $object ) && is_a( $object, $this->appointment_model_object ) ) {

            $id = $object->get( 'ID' );

        }

        return $id;
    }

    /**
	 * Handle and return `Appointment_Model` class method with parameters.
	 *
	 * @param $result
	 * @param $prop
	 * @param $object
	 *
	 * @return false|mixed|string
	 */
    public function get_appointment_prop( $value, $prop, $object ) {

        if ( $object && is_object( $object ) && is_a( $object, $this->appointment_model_object ) ) {

            $prefix = $this->appointment_fields_prefix;

            if ( strpos( $prop, $prefix ) === 0 ) {
                $result = substr( $prop, strlen( $prefix ) );
                $value = $object->get( $result );
            }

        }

        return $value;
    }

	/**
	 * Returns `Appointment_Model` fields meta.
	 *
	 * @param $value
	 * @param $meta_key
     * @param $object
	 *
	 * @return false|mixed|void
	 */
    public function get_appointment_meta( $value, $meta_key, $object ) {

        if ( $object && is_object( $object ) && is_a( $object, $this->appointment_model_object ) ) {
			$prefix = $this->appointment_fields_prefix;

			if ( 0 === strpos( $meta_key, $prefix ) ) {
				$meta_key = substr( $meta_key, strlen( $prefix ) );
			}

            $value = Plugin::instance()->db->appointments_meta->get_meta( $object->get( 'ID' ), $meta_key );
        }

        return $value;
    }

	/**
	 * Returns the instance.
	 *
	 * @access public
	 *
	 * @return object
	 */
	public static function instance() {

		// If the single instance hasn't been set, set it now.
		if ( null == self::$instance ) {
			self::$instance = new self;
		}

		return self::$instance;

	}

}
