<?php
namespace SabaiApps\Directories\Component\Field\Renderer;

use SabaiApps\Directories\Application;
use SabaiApps\Directories\Component\Field\IField;
use SabaiApps\Directories\Component\Entity\Type\IEntity;
use SabaiApps\Directories\Component\Entity\Model\Bundle;

abstract class AbstractRenderer implements IRenderer {

	protected $_application, $_name, $_info;

	public function __construct( Application $application, $name ) {
		$this->_application = $application;
		$this->_name        = $name;
	}

	public function fieldRendererInfo( $key = null ) {
		if ( ! isset( $this->_info ) ) {
			$this->_info = (array) $this->_fieldRendererInfo();
		}

		return isset( $key ) ? ( isset( $this->_info[ $key ] ) ? $this->_info[ $key ] : null ) : $this->_info;
	}

	public function fieldRendererOnRender( IField $field, array $settings ) {}

	public function fieldRendererSettingsForm( IField $field, array $settings, array $parents = array() ) {
		$form = (array) $this->_fieldRendererSettingsForm( $field, $settings, $parents );
		if ( ! $this->fieldRendererInfo( 'accept_multiple' ) ) {
			if ( 1 !== $max_num_items = $field->getFieldMaxNumItems() ) {
				$form += array(
					'_limit' => array(
						'#type'          => 'slider',
						'#integer'       => true,
						'#min_value'     => 0,
						'#max_value'     => $max_num_items === 0 ? 20 : $max_num_items,
						'#min_text'      => __( 'Unlimited', 'directories-pro' ),
						'#title'         => __( 'Max items to display', 'directories-pro' ),
						'#default_value' => isset( $settings['_limit'] ) ? $settings['_limit'] : null,
						'#weight'        => 100,
					),
				);
				if ( false !== $this->fieldRendererInfo( 'separatable' ) ) {
					$form += array(
						'_separator' => array(
							'#states'        => array(
								'invisible' => array(
									sprintf( 'input[name="%s[_limit]"]', $this->_application->Form_Form_fieldName( $parents ) ) => array( 'value' => 1 ),
								),
							),
							'#type'          => 'textfield',
							'#title'         => __( 'Field value separator', 'directories-pro' ),
							'#min_length'    => 1,
							'#default_value' => isset( $settings['_separator'] ) ? $settings['_separator'] : null,
							'#weight'        => 101,
							'#no_trim'       => true,
						),
					);
				}
			} elseif ( false !== $this->fieldRendererInfo( 'separatable' ) ) {
					$form += array(
						'_separator' => array(
							'#type'          => 'hidden',
							'#default_value' => isset( $settings['_separator'] ) ? $settings['_separator'] : null,
						),
					);
			}
		}
		return $form;
	}

	public function fieldRendererAmpSettingsForm( IField $field, array $settings, array $parents = array() ) {}

	public function fieldRendererRenderField( IField $field, array &$settings, IEntity $entity, ?array $values = null, ?array $context = null ) {
		if ( ! isset( $values ) ) {
			$values = $entity->getFieldValue( $field->getFieldName() );
		}
		$more = 0;
		if ( ! empty( $values )
			&& is_array( $values )
		) {
			$offset = empty( $settings['_offset'] ) ? 0 : $settings['_offset'];
			$limit  = empty( $settings['_limit'] ) ? null : $settings['_limit'];
			if ( $offset || $limit ) {
				$count = count( $values );
				if ( 0 > $more = $count - $offset - (int) $limit ) {
					$more = 0;
				}
				$values = array_slice( $values, $offset, $limit );
			}
		}

		return $this->_fieldRendererRenderField( $field, $settings, $entity, $values, $context, $more );
	}

	abstract protected function _fieldRendererInfo();
	abstract protected function _fieldRendererRenderField( IField $field, array &$settings, IEntity $entity, array $values, ?array $context = null, $more = 0 );

	protected function _fieldRendererSettingsForm( IField $field, array $settings, array $parents = array() ) {}

	public function fieldRendererIsPreRenderable( IField $field, array $settings ) {
		return false;
	}

	public function fieldRendererPreRender( IField $field, array $settings, array $entities = array() ) {}

	public function fieldRendererReadableSettings( IField $field, array $settings ) {
		$ret = (array) $this->_fieldRendererReadableSettings( $field, $settings );
		uasort(
			$ret,
			function ( $a, $b ) {
				if ( ! isset( $a['weight'] ) ) {
					$a['weight'] = 0;
				}
				if ( ! isset( $b['weight'] ) ) {
					$b['weight'] = 0;
				}
				return (int) $a['weight'] < (int) $b['weight'] ? -1 : 1;
			}
		);
		if ( ! $this->fieldRendererInfo( 'accept_multiple' )
			&& ( 1 !== $field->getFieldMaxNumItems() )
		) {
			$ret['_limit'] = array(
				'label' => __( 'Max items to display', 'directories-pro' ),
				'value' => empty( $settings['_limit'] ) ? __( 'Unlimited', 'directories-pro' ) : $settings['_limit'],
			);
			if ( false !== $this->fieldRendererInfo( 'separatable' )
				&& isset( $settings['_separator'] )
				&& strlen( $settings['_separator'] )
			) {
				$ret['_separator'] = array(
					'label' => __( 'Field value separator', 'directories-pro' ),
					'value' => $settings['_separator'],
				);
			}
		}
		return $ret;
	}

	protected function _fieldRendererReadableSettings( IField $field, array $settings ) {}

	public function fieldRendererSupports( Bundle $bundle, IField $field ) {
		return true;
	}

	public function fieldRendererSupportsAmp( Bundle $bundle ) {
		return false;
	}

	protected function _getLinkTargetOptions( $includeSelf = false ) {
		$ret = array(
			''       => __( 'Current window', 'directories-pro' ),
			'_blank' => __( 'New window', 'directories-pro' ),
		);
		if ( $includeSelf ) {
			$ret['_self'] = $ret[''];
		}
		return $ret;
	}

	protected function _getLinkRelAttrOptions() {
		return array(
			'nofollow'  => __( 'Add "nofollow"', 'directories-pro' ),
			'external'  => __( 'Add "external"', 'directories-pro' ),
			'ugc'       => __( 'Add "ugc"', 'directories-pro' ),
			'sponsored' => __( 'Add "sponsored"', 'directories-pro' ),
		);
	}

	protected function _getImageSizeOptions() {
		return array(
			'thumbnail'        => __( 'Thumbnail', 'directories-pro' ),
			'thumbnail_scaled' => __( 'Thumbnail (scaled)', 'directories-pro' ),
			'medium'           => __( 'Medium size', 'directories-pro' ),
			'large'            => __( 'Large size', 'directories-pro' ),
			'full'             => __( 'Original size', 'directories-pro' ),
		);
	}
}
