<?php
/**
 * PPOM Meta Class
 * Manages a PPOM Fields Group
 *
 * @since version 15.0
 */

class PPOM_Meta {

	protected static $wc_product;
	private static $ins = null;
	public static $product_id;

	/**
	 * Plugin category data.
	 *
	 * @var array $category_meta
	 */
	public $category_meta = array();

	/**
	 * Plugin category array.
	 *
	 * @var array $ppom_categories_and_tags_row
	 */
	public $ppom_categories_and_tags_row = array();

	/**
	 * Plugin settings.
	 *
	 * @var array $ppom_settings
	 */
	public $ppom_settings = array();

	/**
	 * Fields.
	 *
	 * @var bool $is_exists
	 */
	public $is_exists = false;

	/**
	 * Meta ID.
	 *
	 * @var int $single_meta_id
	 */
	public $single_meta_id = 0;

	/**
	 * Check has multiple meta.
	 *
	 * @var bool $has_multiple_meta
	 */
	public $has_multiple_meta = false;

	/**
	 * Check ajax validation enabled or not.
	 *
	 * @var bool $ajax_validation_enabled
	 */
	public $ajax_validation_enabled = false;

	/**
	 * Inline CSS.
	 *
	 * @var string $inline_css
	 */
	public $inline_css = '';

	/**
	 * Inline JS.
	 *
	 * @var string $inline_js
	 */
	public $inline_js = '';

	/**
	 * Price display.
	 *
	 * @var string $price_display
	 */
	public $price_display = '';

	/**
	 * Meta title.
	 *
	 * @var string $meta_title
	 */
	public $meta_title = '';

	/**
	 * Fields.
	 *
	 * @var array $fields
	 */
	public $fields = array();

	// QM-5
	var $meta_id;

	// $product_id can be null if get instance to get data by meta_id
	function __construct( $product_id = null ) {

		self::$wc_product                   = wc_get_product( $product_id );
		$this->category_meta                = [];
		$this->ppom_categories_and_tags_row = $this->all_ppom_with_categories();
		$this->meta_id                      = $this->get_meta_id( $product_id );
		self::$product_id                   = $product_id;


		$this->ppom_settings = $this->settings();
		$this->fields        = $this->get_fields();

		// Now we are creating properties agains each methods in our Alpha class.
		$methods          = get_class_methods( $this );
		$excluded_methods = array(
			'__construct',
			'get_settings_by_id',
			'get_fields_by_id',
			'settings',
			'all_ppom_with_categories',
			'ppom_has_category_meta',
			'get_meta_id',
			'get_fields',
			'has_unique_datanames',
			'get_instance',
		);

		foreach ( $methods as $method ) {
			if ( ! in_array( $method, $excluded_methods ) ) {
				$this->$method = $this->$method();
			}
		}

		// Retrieve fields with the repeater enabled.
		$is_cloned = is_array( $this->fields ) ? array_filter( array_column( $this->fields, 'is_cloned' ) ) : array();
		if ( isset( $this->ppom_settings->productmeta_validation ) && ! empty( $is_cloned ) ) {
			$this->ppom_settings->productmeta_validation = 'on';
		}
	}

	public static function get_instance( $product_id ) {

		// ALERT: This cause issues .. April 16, 2021: Najeeb
		// ( $product_id != self::$product_id || is_null(self::$ins) ) &&  self::$ins = new PPOM_Meta($product_id);

		is_null( self::$ins ) && self::$ins = new PPOM_Meta( $product_id );

		return self::$ins;
	}

	// QM-5
	function get_meta_id( $product_id ) {

		$ppom_product_id = get_post_meta( $product_id, PPOM_PRODUCT_META_KEY, true );

		if ( $ppom_product_id == 0 || $ppom_product_id == 'None' ) {
			$ppom_product_id = null;
		}


		// Checking if PPOM attached in category
		$ppom_in_category = $this->ppom_has_category_meta( $product_id );
		// if( $ppom_in_category && ! is_admin() ){
		if ( $ppom_in_category ) {

			/**
			 * checking product against categories
			 *
			 * @since 6.4
			 */

			$ppom_overrides = apply_filters( 'ppom_meta_overrides', 'default' );

			switch ( $ppom_overrides ) {

				case 'category_override':
					$ppom_product_id = $ppom_in_category;
					break;
				case 'individual_override':
					// Check for a categorical assignment in the event an individual assignment does not exist for this product in the wp_options table
					if ( $ppom_product_id === null ) {
						$ppom_product_id = $ppom_in_category;
					}
					break;
				default:
					if ( is_array( $ppom_product_id ) && ! in_array( $ppom_in_category, $ppom_product_id ) ) {

						$ppom_priority = apply_filters( 'ppom_meta_priority', 'category_first' );

						if ( $ppom_priority == 'category_first' ) {

							$ppom_product_id = array_merge( $ppom_in_category, $ppom_product_id );
						} else {
							$ppom_product_id = array_merge( $ppom_product_id, $ppom_in_category );
						}
					} elseif ( ! $ppom_product_id ) { // If no meta groups attached to products

						$ppom_product_id = $ppom_in_category;
					}
					break;

			}
		}

		return apply_filters( 'ppom_product_meta_id', is_array( $ppom_product_id ) ? array_unique( $ppom_product_id ) : $ppom_product_id, $product_id );
	}

	// Properties functions
	function is_exists() {

		if ( $this->meta_id == 0 || $this->meta_id == 'None' ) {
			$this->meta_id = null;
		}


		return $this->meta_id == null ? false : true;
	}


	// since 15.0 multiple meta can be set against single product
	// so we have to set one active one meta for compatiblility isues
	// QM-5
	function single_meta_id() {

		$single_meta = ( $this->meta_id == 0 || $this->meta_id == 'None' || empty( $this->meta_id ) ) ? null : $this->meta_id;

		if ( is_array( $single_meta) && 0 < count( $single_meta ) ) {
			$single_meta =  $single_meta[0];
		}

		return $single_meta;
	}

	// QM-5
	function has_multiple_meta() {

		$multiple_meta = false;
		if ( is_array( $this->meta_id ) ) {
			$multiple_meta = true;
		}

		return $multiple_meta;
	}

	// getting settings
	// QM-5
	function settings() {

		$meta_id = $this->single_meta_id();

		if ( ! $meta_id || $meta_id == __( 'None', 'woocommerce-product-addon' ) ) {
			return null;
		}

		global $wpdb;

		if ( is_array( $meta_id ) ) {
			$meta_id = implode( ',', $meta_id );
		}

		$qry           = 'SELECT * FROM ' . $wpdb->prefix . PPOM_TABLE_META . " WHERE productmeta_id IN($meta_id)";
		$meta_settings = $wpdb->get_results( $qry );
		$filter_meta   = array_filter(
			$meta_settings,
			function( $meta ) {
				return 'on' === $meta->productmeta_validation ? $meta : false;
			}
		);
		$meta_settings = ! empty( $filter_meta ) ? reset( $filter_meta ) : reset( $meta_settings );

		$meta_settings = empty( $meta_settings ) ? null : $meta_settings;

		return apply_filters( 'ppom_meta_settings', $meta_settings, $this );
	}

	// getting fields
	function get_fields() {

		if ( ! $this->is_exists() ) {
			return null;
		}

		// Meta created without any fields
		if ( ! $this->ppom_settings ) {
			return null;
		}

		$meta_fields = array();
		global $wpdb;
		if ( $this->has_multiple_meta() ) {

			foreach ( $this->meta_id as $meta_id ) {
				$qry    = 'SELECT the_meta FROM ' . $wpdb->prefix . PPOM_TABLE_META . " WHERE productmeta_id = {$meta_id}";
				$fields = $wpdb->get_var( $qry );

				if ( ! is_string( $fields ) || empty( $fields ) ) {
					continue;
				}

				$fields = json_decode( $fields, true );

				if ( is_array( $fields ) ) {
					$meta_fields = array_merge( $meta_fields, $fields );
				}
			}
		} else {
			$meta_id     = $this->meta_id;
			$qry         = 'SELECT the_meta FROM ' . $wpdb->prefix . PPOM_TABLE_META . " WHERE productmeta_id = {$meta_id}";
			$fields      = $wpdb->get_var( $qry );
			$meta_fields = json_decode( $fields, true );
		}

		// Filter fields which are active only
		$meta_fields = array_filter(
			(array) $meta_fields,
			function ( $field ) {
				return ! isset( $field['status'] ) || $field['status'] == 'on';
			}
		);

		// ppom_pa($meta_fields);

		return apply_filters( 'ppom_meta_fields', $meta_fields, $this );
	}

	// Getting fields by meta id
	function get_fields_by_id( $ppom_id ) {

		$meta_fields = array();
		global $wpdb;

		$ppom_ids = explode( ',', $ppom_id );
		foreach ( $ppom_ids as $meta_id ) {

			$table  = $wpdb->prefix . PPOM_TABLE_META;
			$fields = $wpdb->get_var( $wpdb->prepare( "SELECT the_meta FROM $table WHERE productmeta_id = %d", $meta_id ) );
			$fields = json_decode( $fields, true );
			if ( is_array( $fields ) ) {
				$meta_fields = array_merge( $meta_fields, $fields );
			}
		}

		// Filter fields which are active only
		$meta_fields = array_filter(
			$meta_fields,
			function ( $field ) {
				return ! isset( $field['status'] ) || $field['status'] == 'on';
			}
		);

		$meta_fields = array_filter(
			$meta_fields,
			function ( $field ) {
				return ! isset( $field['status'] ) || $field['status'] == 'on';
			}
		);

		// if( empty($meta_fields) ) return null;

		return apply_filters( 'ppom_meta_fields_by_id', $meta_fields, $ppom_ids, $this );
	}

	function ppom_has_category_meta($product_id ) {

		$product_categories = get_the_terms( $product_id, 'product_cat' );

		$meta_found = array();
		if ( $product_categories && $this->ppom_categories_and_tags_row ) {
			foreach ( $this->ppom_categories_and_tags_row as $row ) {

				if ( $row->productmeta_categories === 'All' ) {
					$meta_found[] = $row->productmeta_id;
				} else {
					// making array of meta cats

					$meta_cat_array = preg_split('/\r\n|\n/', $row->productmeta_categories);
					// Now iterating the product_categories to check it's slug in meta cats
					foreach ( $product_categories as $cat ) {
						if ( in_array( $cat->slug, $meta_cat_array ) ) {
							$meta_found[] = $row->productmeta_id;
						}
					}
				}
			}
		}

		$meta_found = apply_filters( 'ppom_pro_fields_to_display_on_product', $meta_found, $product_id, $this->ppom_categories_and_tags_row );

		$this->category_meta = $meta_found;

		return $meta_found;
	}

	function all_ppom_with_categories() {

		global $wpdb;
		$ppom_table = $wpdb->prefix . PPOM_TABLE_META;

		$qry = "SELECT productmeta_id, productmeta_categories, productmeta_tags FROM {$ppom_table} WHERE productmeta_categories != '' OR productmeta_tags != ''";

		return $wpdb->get_results( $qry );
	}

	// check meta settings: ajax validation
	function ajax_validation_enabled() {

		$validation_enabled = false;

		if ( ! $this->is_exists() ) {
			return null;
		}

		// Meta created without any fields
		if ( ! $this->ppom_settings ) {
			return null;
		}

		return apply_filters( 'ppom_ajax_validation_enabled', $validation_enabled, $this );
	}

	// check meta settings: styels
	function inline_css() {

		$inline_css = '';

		if ( ! $this->is_exists() ) {
			return null;
		}

		// Meta created without any fields
		if ( ! $this->ppom_settings ) {
			return null;
		}

		if (
			isset( $this->ppom_settings->productmeta_style ) &&
			is_string( $this->ppom_settings->productmeta_style ) &&
			$this->ppom_settings->productmeta_style !== ''
		) {
			$selector = '';
			$template = stripslashes( strip_tags( $this->ppom_settings->productmeta_style ) );

			if ( is_array( $this->meta_id ) ) {
				$field_selector = [];
				foreach( $this->meta_id as $field_id ) {
					$field_selector[] = ".ppom-id-" . $field_id;
				}
				$selector = ':where(' . implode( ', ', $field_selector ) . ')';
			} else if ( is_numeric( $this->meta_id ) ) {
				$selector = ".ppom-id-" . $this->meta_id;
			}
			$inline_css = str_replace( 'selector', $selector, $template );
		}

		return apply_filters( 'ppom_inline_css', $inline_css, $this );
	}

	// check meta settings: styels
	function inline_js() {

		$inline_js = '';

		if ( ! $this->is_exists() ) {
			return null;
		}

		// Meta created without any fields
		if ( ! $this->ppom_settings ) {
			return null;
		}

		if ( isset( $this->ppom_settings->productmeta_js ) && $this->ppom_settings->productmeta_js != '' ) {
			$inline_js = stripslashes( strip_tags( $this->ppom_settings->productmeta_js ) );
		}

		return apply_filters( 'ppom_inline_js', $inline_js, $this );
	}

	// check meta settings: styels
	function price_display() {

		$price_display = '';

		if ( ! $this->is_exists() ) {
			return null;
		}

		// Meta created without any fields
		if ( ! $this->ppom_settings ) {
			return null;
		}

		$price_display = $this->ppom_settings->dynamic_price_display;

		return apply_filters( 'ppom_price_display', $price_display, $this );
	}

	// check meta settings: styels
	function meta_title() {

		$meta_title = '';

		if ( ! $this->is_exists() ) {
			return null;
		}

		// Meta created without any fields
		if ( ! $this->ppom_settings ) {
			return null;
		}

		$meta_title = stripslashes( $this->ppom_settings->productmeta_name );

		return apply_filters( 'ppom_meta_title', $meta_title, $this );
	}

	// Since 15.1: checking if all meta has unique datanames
	function has_unique_datanames() {

		if ( ! $this->fields ) {
			return false;
		}

		$has_unique      = true;
		$datanames_array = array();

		// ppom_pa($this->fields);

		foreach ( $this->fields as $field ) {

			$type = isset( $field['type'] ) ? $field['type'] : '';

			// pricematrix does not have dataname
			if ( $type == 'pricematrix' ) {
				continue;
			}
			// ignore collapased fields
			if ( $type == 'collapse' ) {
				continue;
			}

			if ( ! isset( $field['data_name'] ) ) {
				$has_unique = false;
				break;
			}

			if ( in_array( $field['data_name'], $datanames_array ) ) {

				$has_unique = false;
				break;
			}

			$datanames_array[] = $field['data_name'];

		}

		// ppom_pa($datanames_array);
		return apply_filters( 'ppom_has_unique_fields', $has_unique, $this );
	}

	/* ============== Get settings by metaid  ================= */
	function get_settings_by_id( $meta_id ) {

		global $wpdb;

		$qry           = 'SELECT * FROM ' . $wpdb->prefix . PPOM_TABLE_META . " WHERE productmeta_id = {$meta_id}";
		$table         = $wpdb->prefix . PPOM_TABLE_META;
		$meta_settings = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $table WHERE productmeta_id = %d", $meta_id ) );

		$meta_settings = empty( $meta_settings ) ? null : $meta_settings;

		return apply_filters( 'ppom_get_settings_by_id', $meta_settings, $meta_id, $this );
	}

}
