<?php

namespace wpbuddy\rich_snippets\pro;

use wpbuddy\rich_snippets\Rich_Snippet;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
} // Exit if accessed directly


/**
 * Class ACF_Model.
 *
 * Recognizes ACF plugin and provides new fields.
 *
 * @package wpbuddy\rich_snippets
 *
 * @since   2.24.0
 */
final class ACF_Model {

	/**
	 * @param $values
	 *
	 * @return mixed
	 */
	public static function internal_subselect( $values ) {

		if ( ! function_exists( 'get_field' ) ) {
			return $values;
		}

		$acf_field = array(
			'id'     => 'textfield_acf',
			'label'  => esc_html_x( 'ACF Field', 'subselect field', 'rich-snippets-schema' ),
			'method' => array( 'wpbuddy\rich_snippets\pro\ACF_Model', 'acf_field' ),
		);

		$values['http://schema.org/Text'][]            = $acf_field;
		$values['http://schema.org/XPathType'][]       = $acf_field;
		$values['http://schema.org/Integer'][]         = $acf_field;
		$values['http://schema.org/Time'][]            = $acf_field;
		$values['http://schema.org/DayOfWeek'][]       = $acf_field;
		$values['http://schema.org/Date'][]            = $acf_field;
		$values['http://schema.org/URL'][]             = $acf_field;
		$values['http://schema.org/Duration'][]        = $acf_field;
		$values['http://schema.org/Intangible'][]      = $acf_field;
		$values['http://schema.org/Quantity'][]        = $acf_field;
		$values['http://schema.org/Energy'][]          = $acf_field;
		$values['http://schema.org/Mass'][]            = $acf_field;
		$values['http://schema.org/CssSelectorType'][] = $acf_field;
		$values['http://schema.org/DeliveryMethod'][]  = $acf_field;

		return $values;
	}


	/**
	 * Returns the value of an ACF field.
	 *
	 * @param                                     $val
	 * @param \wpbuddy\rich_snippets\Rich_Snippet $rich_snippet
	 * @param array $meta_info
	 * @param bool $overwritten
	 *
	 * @return string|array
	 * @since 2.24.0
	 */
	public static function acf_field( $val, Rich_Snippet $rich_snippet, array $meta_info, bool $overwritten ) {

		if ( ! function_exists( 'get_field_object' ) ) {
			return '';
		}

		$in_the_loop = isset( $meta_info['in_the_loop'] ) && $meta_info['in_the_loop'];

		if ( $in_the_loop ) {
			$o = call_user_func( function () use ( $meta_info, $val ) {
				if ( ! is_array( $meta_info['object'] ) ) {
					return false;
				}

				foreach ( $meta_info['object'] as $object ) {
					if ( $object['name'] === $val ) {
						return $object;
					}
				}

				return false;
			} );
		} else {
			if ( $meta_info['queried_object'] instanceof \WP_Post ) {
				$field_name = $meta_info['current_post_id'];
			} elseif ( $meta_info['queried_object'] instanceof \WP_User ) {
				$field_name = 'user_' . $meta_info['queried_object']->ID;
			} elseif ( $meta_info['queried_object'] instanceof \WP_Term ) {
				$field_name = $meta_info['queried_object']->taxonomy . '_' . $meta_info['queried_object']->term_taxonomy_id;
			} else {
				return '';
			}

			$o = get_field_object(
				false !== stripos( $val, '->' ) ? strstr( $val, '->', true ) : $val,
				$field_name
			);
		}


		if ( ! is_array( $o ) ) {
			return '';
		}

		if ( is_scalar( $o['value'] ) && empty( $o['value'] ) ) {
			return '';
		}

		if ( count( $o ) <= 0 ) {
			return '';
		}

		switch ( $o['type'] ) {
			case 'text':
			case 'textarea':
				return (string) $o['value'];
			case 'range':
			case 'number':
				if ( false !== stripos( $o['value'], '.' ) ) {
					return (float) $o['value'];
				}

				return (int) $o['value'];
			case 'email':
				return sanitize_email( $o['value'] );
			case 'url';
				return esc_url_raw( $o['value'] );
			case 'image':
				$is_id = is_scalar( $o['value'] ) && is_numeric( $o['value'] );

				if ( $is_id ) {
					$image = wp_get_attachment_image_src( (int) $o['value'], 'full', false );

					if ( ! $image ) {
						return '';
					}

					return esc_url_raw( $image[0] );
				}

				switch ( $o['return_format'] ) {
					case 'array':
						return esc_url_raw( $o['value']['url'] );
					case 'url':
						return esc_url_raw( $o['value'] );
				}

				return '';
			case 'file':
				switch ( $o['return_format'] ) {
					case 'array':
						return esc_url_raw( $o['value']['url'] );
					case 'url':
						return esc_url_raw( $o['value'] );
					case 'id':
						return esc_url_raw( wp_get_attachment_url( $o['value'] ) );
				}

				return '';
			case 'wysiwyg':
				return Helper_Model::instance()->filter_html( $o['value'] );
			case 'gallery':
				$images = [];
				foreach ( (array) $o['value'] as $gallery_item ) {
					switch ( $o['return_format'] ) {
						case 'array':
							$images[] = esc_url_raw( $gallery_item['url'] );
							break;
						case 'url':
							$images[] = esc_url_raw( $gallery_item );
							break;
						case 'id':
							$images[] = esc_url_raw( wp_get_attachment_url( $gallery_item ) );
							break;
					}
				}

				return $images;
			case 'checkbox':
			case 'select':
				if ( 'array' === $o['return_format'] ) {
					return wp_list_pluck( (array) $o['value'], 'value' );
				}

				return $o['value'];
			case 'radio':
				if ( 'array' === $o['return_format'] ) {
					return $o['value']['value'];
				}

				return $o['value'];
			case 'true_false':
				return sprintf( 'https://schema.org/%s', $o['value'] ? 'True' : 'False' );
			case 'link':
				if ( 'array' === $o['return_format'] ) {
					return esc_url_raw( $o['value']['url'] );
				}

				return esc_url_raw( $o['value'] );
			case 'page_link':
				if ( $o['multiple'] ) {
					return array_map( 'esc_url_raw', $o['value'] );
				}

				return esc_url_raw( $o['value'] );
			case 'taxonomy':
				$helper = Helper_Model::instance();
				$terms  = array_map( function ( $term_or_id ) use ( $o, $helper, $val ) {
					$term = get_term( $term_or_id, $o['taxonomy'] );

					if ( $term instanceof \WP_Term ) {
						return $helper->get_deep( $term, str_replace( $o['name'], '', $val ) );
					}

					return '';
				}, $o['value'] );

				return array_filter( $terms );
			case 'post_object':
				$helper = Helper_Model::instance();

				$posts = $o['multiple'] ? $o['value'] : [ $o['value'] ];

				$posts = array_map( function ( $term_or_id ) use ( $o, $helper, $val ) {
					$post = get_post( $term_or_id );

					if ( $post instanceof \WP_Post ) {
						return $helper->get_deep( $post, str_replace( $o['name'], '', $val ) );
					}

					return '';
				}, $posts );

				return array_filter( $posts );
			case 'user':
				$helper = Helper_Model::instance();

				$users = $o['multiple'] ? $o['value'] : [ $o['value'] ];

				$users = array_map( function ( $user_or_id ) use ( $o, $helper, $val ) {
					if ( 'array' === $o['return_format'] ) {
						$user = get_user_by( 'ID', $user_or_id['ID'] );
					} elseif ( 'object' === $o['return_format'] ) {
						$user = get_user_by( 'ID', $user_or_id->ID );
					} else {
						$user = get_user_by( 'ID', $user_or_id );
					}

					if ( $user instanceof \WP_User ) {
						return $helper->get_deep( $user, str_replace( $o['name'], '', $val ) );
					}

					return '';
				}, $users );

				return array_filter( $users );
			case 'date_picker':
			case 'date_time_picker':
			case 'time_picker':
				try {
					$datetime = \DateTimeImmutable::createFromFormat( $o['return_format'], $o['value'], wp_timezone() );
				} catch ( \Exception $e ) {
					return '';
				}

				if ( ! $datetime ) {
					return '';
				}

				return $datetime->format( 'time_picker' === $o['type'] ? 'G:i:s' : 'c' );
			case 'google_map':

				if ( ! is_array( $o['value'] ) ) {
					return '';
				}

			case 'repeater':
				$helper              = Helper_Model::instance();
				$repeater_field_name = substr( $val, strpos( $val, '->' ) );
				$t                   = $helper->get_deep( $o['value'], $repeater_field_name );
				$t                   = array_reduce( $t, 'array_merge', [] );

				return $t;
		}

		/**
		 * not supported fields
		 * * password
		 */

		return '';
	}


	/**
	 * Adds repeater fields for use inside loops.
	 *
	 * @param array $values
	 *
	 * @return array
	 * @since 2.25.0
	 */
	public static function loop_fields( $values ) {

		if ( ! function_exists( 'acf_get_raw_field_groups' ) ) {
			return $values;
		}

		$raw_field_groups = acf_get_raw_field_groups();

		foreach ( $raw_field_groups as $raw_field_group ) {
			$fields = acf_get_fields( $raw_field_group );
			foreach ( $fields as $field ) {
				if ( 'repeater' !== $field['type'] ) {
					continue;
				}

				$values[ 'acf_repeater_' . $field['name'] ] = sprintf(
					__( 'ACF Repeater: %s (from "%s" field group)', 'rich-snippets-schema' ),
					esc_html( $field['label'] ),
					esc_html( $raw_field_group['title'] )
				);
			}
		}

		return $values;
	}


	/**
	 * Returns the loop items.
	 *
	 * @param array $items
	 * @param Rich_Snippet $snippet
	 * @param int $post_id
	 * @param object $meta_info
	 *
	 * @return array
	 * @since 2.15.0
	 * @since 2.25.2 Added $meta_info
	 */
	public static function loop_items( $items, $snippet, $post_id, $meta_info ) {
		if ( ! function_exists( 'get_field_object' ) ) {
			return $items;
		}

		if ( false === stripos( $snippet->get_loop_type(), 'acf_repeater' ) ) {
			return $items;
		}

		$repeater_name = str_replace( 'acf_repeater_', '', $snippet->get_loop_type() );

		if ( $meta_info['queried_object'] instanceof \WP_Post ) {
			$field_name = $post_id;
		} elseif ( $meta_info['queried_object'] instanceof \WP_User ) {
			$field_name = 'user_' . $meta_info['queried_object']->ID;
		} elseif ( $meta_info['queried_object'] instanceof \WP_Term ) {
			$field_name = $meta_info['queried_object']->taxonomy . '_' . $meta_info['queried_object']->term_taxonomy_id;
		} else {
			return $items;
		}

		$field = get_field_object( $repeater_name, $field_name );

		if ( ! isset( $field['sub_fields'] ) ) {
			return $items;
		}

		$sub_fields = $field['sub_fields'];

		if ( ! have_rows( $repeater_name, $field_name ) ) {
			return $items;
		}

		$fc = function ( $field_id ) use ( $sub_fields ) {
			foreach ( $sub_fields as $sub_field ) {
				if ( $sub_field['key'] === $field_id ) {
					return $sub_field;
				}
			}

			return false;
		};

		while ( have_rows( $repeater_name, $field_name ) ) {
			the_row();
			$row    = get_row( false );
			$fields = [];
			foreach ( $row as $field_id => $field_value ) {
				$r = $fc( $field_id );

				if ( false === $r ) {
					continue;
				}

				$r['value'] = $field_value;

				$fields[] = $r;
			}
			$items[] = $fields;
		}

		return $items;
	}
}
