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

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

class ImageRenderer extends AbstractRenderer {

	protected function _fieldRendererInfo() {
		return array(
			'field_types'      => array( 'wp_image', 'file_image' ),
			'default_settings' => array(
				'size'            => 'thumbnail',
				'width'           => 0,
				'height'          => 0,
				'cols'            => 4,
				'gutter_width'    => 'none',
				'link'            => 'photo',
				'link_image_size' => 'large',
				'link_target'     => '',
			),
			'separatable'      => false,
			'no_imageable'     => true,
		);
	}

	public function fieldRendererSettingsForm( IField $field, array $settings, array $parents = array() ) {
		$form = parent::fieldRendererSettingsForm( $field, $settings, $parents );
		if ( isset( $form['_limit'] ) ) {
			$background_setting_selector = sprintf( '[name="%s[_render_background]"]', $this->_application->Form_Form_fieldName( $parents ) );
			$form['_limit']['#states']['invisible'][ $background_setting_selector ] = array(
				'type'  => 'checked',
				'value' => true,
			);
		}

		return $form;
	}

	protected function _fieldRendererSettingsForm( IField $field, array $settings, array $parents = array() ) {
		$background_setting_selector = sprintf( '[name="%s[_render_background]"]', $this->_application->Form_Form_fieldName( $parents ) );
		$form                        = array(
			'size'            => array(
				'#title'         => __( 'Image size', 'directories-pro' ),
				'#type'          => 'select',
				'#options'       => $this->_getImageSizeOptions(),
				'#default_value' => $settings['size'],
				'#weight'        => 1,
			),
			'width'           => array(
				'#title'         => __( 'Image width', 'directories-pro' ),
				'#type'          => 'slider',
				'#min_value'     => 0,
				'#max_value'     => 100,
				'#min_text'      => __( 'Auto', 'directories-pro' ),
				'#integer'       => true,
				'#default_value' => $settings['width'],
				'#weight'        => 2,
				'#field_suffix'  => '%',
				'#states'        => array(
					'invisible' => array(
						$background_setting_selector => array(
							'type'  => 'checked',
							'value' => true,
						),
					),
				),
			),
			'height'          => array(
				'#title'         => __( 'Image height', 'directories-pro' ),
				'#type'          => 'slider',
				'#min_value'     => 0,
				'#min_text'      => __( 'Auto', 'directories-pro' ),
				'#max_value'     => 500,
				'#integer'       => true,
				'#default_value' => $settings['height'],
				'#weight'        => 2,
				'#field_suffix'  => 'px',
			),
			'link'            => array(
				'#type'          => 'select',
				'#title'         => __( 'Link image to', 'directories-pro' ),
				'#options'       => $this->_getImageLinkTypeOptions( $field->Bundle ),
				'#default_value' => $settings['link'],
				'#weight'        => 5,
			),
			'link_image_size' => array(
				'#title'         => __( 'Linked image size', 'directories-pro' ),
				'#type'          => 'select',
				'#options'       => $this->_getLinkedImageSizeOptions(),
				'#default_value' => $settings['link_image_size'],
				'#states'        => array(
					'visible' => array(
						sprintf( 'select[name="%s[link]"]', $this->_application->Form_Form_fieldName( $parents ) ) => array( 'value' => 'photo' ),
					),
				),
				'#weight'        => 6,
			),
			'link_target'     => array(
				'#title'         => __( 'Open link in', 'directories-pro' ),
				'#type'          => 'select',
				'#options'       => $this->_getLinkTargetOptions(),
				'#default_value' => $settings['link_target'],
				'#states'        => array(
					'visible' => array(
						sprintf( 'select[name="%s[link]"]', $this->_application->Form_Form_fieldName( $parents ) ) => array(
							'type'  => 'one',
							'value' => $this->_getImageLinkTargetableOptions(),
						),
					),
				),
				'#weight'        => 7,
			),
		);
		// Allow linking title to another field if any linkable field exists
		if ( ( $bundle = $field->Bundle )
			&& ( $linkable_fields = $this->_application->Entity_Field_options(
				$bundle,
				array(
					'interface'       => 'Field\Type\ILinkable',
					'return_disabled' => true,
				)
			) )
		) {
			$form['link_field'] = array(
				'#type'             => 'select',
				'#default_value'    => $settings['link_field'],
				'#options'          => $linkable_fields[0],
				'#options_disabled' => array_keys( $linkable_fields[1] ),
				'#weight'           => 5,
				'#required'         => function ( $form ) use ( $parents ) {
					return in_array( $form->getValue( array_merge( $parents, array( 'link' ) ) ), array( 'field' ) ); },
				'#states'           => array(
					'visible' => array(
						sprintf( 'select[name="%s[link]"]', $this->_application->Form_Form_fieldName( $parents ) ) => array(
							'type'  => 'one',
							'value' => array( 'field' ),
						),
					),
				),
			);
			$form['link_rel']   = array(
				'#title'         => __( 'Add to "rel" attribute', 'directories-pro' ),
				'#weight'        => 5,
				'#type'          => 'checkboxes',
				'#options'       => $this->_getLinkRelAttrOptions(),
				'#default_value' => $settings['link_rel'],
				'#states'        => array(
					'visible' => array(
						sprintf( 'select[name="%s[link]"]', $this->_application->Form_Form_fieldName( $parents ) ) => array(
							'type'  => 'one',
							'value' => array( 'field' ),
						),
					),
				),
			);
		} else {
			$form['link']['#options_disabled'] = array( 'field' );
		}
		if ( $field->getFieldMaxNumItems() !== 1 ) {
			$form['cols']         = array(
				'#title'         => __( 'Number of columns', 'directories-pro' ),
				'#type'          => 'select',
				'#options'       => array(
					1  => 1,
					2  => 2,
					3  => 3,
					4  => 4,
					6  => 6,
					12 => 12,
				),
				'#default_value' => $settings['cols'],
				'#weight'        => 3,
				'#states'        => array(
					'invisible' => array(
						$background_setting_selector => array(
							'type'  => 'checked',
							'value' => true,
						),
					),
				),
			);
			$form['gutter_width'] = array(
				'#title'         => __( 'Space between images', 'directories-pro' ),
				'#type'          => 'select',
				'#default_value' => $settings['gutter_width'],
				'#weight'        => 4,
				'#options'       => array(
					'none' => __( 'None', 'directories-pro' ),
					'xs'   => __( 'Small', 'directories-pro' ),
					'sm'   => __( 'Default', 'directories-pro' ),
					'md'   => __( 'Medium', 'directories-pro' ),
					'lg'   => __( 'Large', 'directories-pro' ),
				),
				'#states'        => array(
					'invisible_or' => array(
						$background_setting_selector => array(
							'type'  => 'checked',
							'value' => true,
						),
						sprintf( 'select[name="%s[cols]"]', $this->_application->Form_Form_fieldName( $parents ) ) => array( 'value' => 1 ),
					),
				),
			);
		}
		$form['_render_background'] = array(
			'#type'          => 'checkbox',
			'#title'         => __( 'Render as background image', 'directories-pro' ),
			'#default_value' => ! empty( $settings['_render_background'] ),
			'#horizontal'    => true,
			'#weight'        => 250,
		);
		$form['_hover_zoom']        = array(
			'#type'          => 'checkbox',
			'#title'         => __( 'Zoom on hover', 'directories-pro' ),
			'#default_value' => ! empty( $settings['_hover_zoom'] ),
			'#horizontal'    => true,
			'#weight'        => 251,
			'#states'        => $render_background_states = array(
				'visible' => array(
					sprintf( 'input[name="%s[_render_background]"]', $this->_application->Form_Form_fieldName( $parents ) ) => array(
						'type'  => 'checked',
						'value' => true,
					),
				),
			),
		);
		$form['_hover_brighten'] = array(
			'#type'          => 'checkbox',
			'#title'         => __( 'Brighten on hover', 'directories-pro' ),
			'#default_value' => ! empty( $settings['_hover_brighten'] ),
			'#horizontal'    => true,
			'#weight'        => 252,
			'#states'        => $render_background_states,
		);

		return $form;
	}

	protected function _getImageLinkTypeOptions( Bundle $bundle ) {
		$ret = array(
			'none'  => __( 'Do not link', 'directories-pro' ),
			'page'  => __( 'Link to post', 'directories-pro' ),
			'field' => __( 'Link to URL of another field', 'directories-pro' ),
		);
		if ( ! empty( $bundle->info['parent'] )
			|| ! empty( $bundle->info['parent_field'] )
		) {
			$ret['parent'] = __( 'Link to parent post', 'directories-pro' );
		}
		$ret['photo'] = __( 'Single image', 'directories-pro' );

		return $ret;
	}

	protected function _getImageLinkTargetableOptions() {
		return array( 'parent', 'page', 'photo' );
	}

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

	protected function _fieldRendererRenderField( IField $field, array &$settings, IEntity $entity, array $values, ?array $context = null, $more = 0 ) {
		$permalink_url = null;
		$rel           = '';
		switch ( $settings['link'] ) {
			case 'page':
				$permalink_url = $this->_application->Entity_PermalinkUrl( $entity );
				break;
			case 'parent':
				if ( $parent_entity = $this->_application->Entity_ParentEntity( $entity, false ) ) {
					$permalink_url = $this->_application->Entity_PermalinkUrl( $parent_entity );
				}
				break;
			case 'field':
				if ( ! empty( $settings['link_field'] )
					&& ( $link_field = $this->_application->Entity_Field( $entity, $settings['link_field'] ) )
					&& ( $link_field_type = $this->_application->Field_Type( $link_field->getFieldType(), true ) )
					&& $link_field_type instanceof ILinkable
					&& ( $url = $link_field_type->fieldLinkableUrl( $link_field, $entity ) )
				) {
					$permalink_url = $url;
					if ( ! empty( $settings['link_rel'] ) ) {
						$rel = implode( ' ', $settings['link_rel'] );
					}
				}
				break;
			default:
		}
		$no_image = empty( $values )
			|| ! $this->_application->Field_Type( $field->getFieldType(), true );
		$target   = $this->_getLinkTarget( $field, $settings );

		// Return image and link URLs only for rendering field as background image
		if ( ! empty( $settings['_render_background'] ) ) {
			$ret = array(
				'html'   => ' ', // add a space so that the display element is rendered
				'target' => $target,
				'class'  => 'drts-display-element-with-background',
			);
			if ( $no_image ) {
				$image_url     = $this->_application->System_NoImage( null, true, $entity );
				$ret['class'] .= ' drts-display-element-with-background-no-image';
				$ret['url']    = in_array( $settings['link'], array( 'page', 'parent' ) ) ? $permalink_url : null;
			} else {
				$image_url = $this->_getImageUrl( $field, $settings, $values[0], $settings['size'] );
				if ( ! empty( $settings['_hover_zoom'] )
					|| ! empty( $settings['_hover_brighten'] )
				) {
					$ret['class'] .= ' drts-display-element-hover-effect';
					if ( ! empty( $settings['_hover_zoom'] ) ) {
						$ret['class'] .= ' drts-display-element-hover-zoom';
					}
					if ( ! empty( $settings['_hover_brighten'] ) ) {
						$ret['class'] .= ' drts-display-element-hover-brighten';
					}
				}
				$ret['url'] = $this->_getImageLinkUrl( $field, $settings, $values[0], $permalink_url, $image_url );
			}
			$ret['style'] = 'background-image:url(' . $this->_application->H( $image_url ) . ');';
			if ( ! empty( $settings['height'] ) ) {
				$ret['style'] .= 'min-height:' . intval( $settings['height'] ) . 'px;';
			}

			return $ret;
		}

		if ( $no_image ) {
			return $this->_getEmptyImage( $settings, $permalink_url, $target, $entity );
		}

		if ( $field->getFieldMaxNumItems() !== 1 ) {
			$col_sm = $col = 12 / $settings['cols'];
			if ( $col_sm < 3 ) {
				$col = 3;
			}
		} else {
			$col_sm = $col = 12;
		}
		if ( $col_sm === 12 && count( $values ) === 1 ) {
			if ( ! $image = $this->_getImage( $field, $settings, $values[0], $permalink_url, $target ) ) {
				return $this->_getEmptyImage( $settings, $permalink_url, $target, $entity );
			}
			return isset( $image['url'] ) ? '<a href="' . $image['url'] . '" target="' . $target . '" rel="' . $rel . '">' . $image['html'] . '</a>' : $image['html'];
		}

		// unset($settings['_hover_zoom'], $settings['_hover_brighten']); // disable hover effects if multiple images
		$ret = array();
		foreach ( $values as $value ) {
			if ( ! $image = $this->_getImage( $field, $settings, $value, $permalink_url, $target ) ) {
				continue;
			}

			$ret[] = sprintf(
				'<div class="drts-col-sm-%1$d drts-col-%2$d">%3$s</div>',
				$col_sm,
				$col,
				isset( $image['url'] ) ? '<a href="' . $image['url'] . '" target="' . ( $target === '_blank' ? $target : '_self' ) . '" rel="' . $rel . '">' . $image['html'] . '</a>' : $image['html']
			);
		}
		if ( empty( $ret ) ) {
			return $this->_getEmptyImage( $settings, $permalink_url, $target, $entity );
		}
		return '<div class="drts-row drts-y-gutter drts-gutter-' . $settings['gutter_width'] . '">' . implode( PHP_EOL, $ret ) . '</div>';
	}

	protected function _getLinkTarget( IField $field, array $settings ) {
		return ! empty( $settings['link_target'] ) && in_array( $settings['link'], $this->_getImageLinkTargetableOptions() ) ? $settings['link_target'] : null;
	}

	protected function _getEmptyImage( array &$settings, $permalinkUrl, $target, IEntity $entity ) {
		return array(
			'url'    => $permalinkUrl,
			'target' => $target,
			'html'   => '<div class="drts-no-image">' . $this->_application->System_NoImage( $settings['size'], false, $entity ) . '</div>',
		);
	}

	protected function _getImage( IField $field, array $settings, $value, $permalinkUrl, $target ) {
		if ( ! $url = $this->_getImageUrl( $field, $settings, $value, $settings['size'] ) ) {
			return '';
		}

		$image = sprintf(
			'<img src="%s" title="%s" alt="%s" style="height:%s;%s" />',
			$url,
			$this->_application->H( $this->_getImageTitle( $field, $settings, $value ) ),
			$this->_application->H( $this->_getImageAlt( $field, $settings, $value ) ),
			empty( $settings['height'] ) ? 'auto' : intval( $settings['height'] ) . 'px',
			empty( $settings['width'] ) ? '' : 'width:' . $settings['width'] . '%;'
		);

		if ( ! empty( $settings['_hover_zoom'] )
			|| ! empty( $settings['_hover_brighten'] )
		) {
			$classes = array( 'drts-display-element-hover-effect' );
			if ( ! empty( $settings['_hover_zoom'] ) ) {
				$classes[] = 'drts-display-element-hover-zoom';

			}
			if ( ! empty( $settings['_hover_brighten'] ) ) {
				$classes[] = 'drts-display-element-hover-brighten';
			}
			$image = '<div class="' . implode( ' ', $classes ) . '">' . $image . '</div>';
		}

		return array(
			'html'   => $image,
			'url'    => $this->_getImageLinkUrl( $field, $settings, $value, $permalinkUrl, $url ),
			'target' => $target,
		);
	}

	protected function _getImageLinkUrl( IField $field, array $settings, $value, $permalinkUrl, $imageUrl ) {
		if ( in_array( $settings['link'], array( 'page', 'parent', 'field' ) ) ) {
			return $permalinkUrl;
		}

		if ( $settings['link'] === 'photo' ) {
			if ( $settings['size'] == $settings['link_image_size'] ) {
				return $imageUrl;
			}

			return $this->_getImageUrl( $field, $settings, $value, $settings['link_image_size'] );
		}
	}

	protected function _getImageUrl( IField $field, array $settings, $value, $size ) {
		return $this->_application->Field_Type( $field->getFieldType() )->fieldImageGetUrl( $value, $size );
	}

	protected function _getImageAlt( IField $field, array $settings, $value ) {
		return $this->_application->Field_Type( $field->getFieldType() )->fieldImageGetAlt( $value );
	}

	protected function _getImageTitle( IField $field, array $settings, $value ) {
		return $this->_application->Field_Type( $field->getFieldType() )->fieldImageGetTitle( $value );
	}

	protected function _fieldRendererReadableSettings( IField $field, array $settings ) {
		$ret = array(
			'size'   => array(
				'label' => __( 'Image size', 'directories-pro' ),
				'value' => $this->_getImageSizeOptions()[ $settings['size'] ],
			),
			'width'  => array(
				'label' => __( 'Image width', 'directories-pro' ),
				'value' => $settings['width'] . '%',
			),
			'height' => array(
				'label' => __( 'Image height', 'directories-pro' ),
				'value' => empty( $settings['height'] ) ? 'auto' : $settings['height'] . 'px',
			),
			'link'   => array(
				'label' => __( 'Link image to', 'directories-pro' ),
				'value' => $this->_getImageLinkTypeOptions( $field->Bundle )[ $settings['link'] ],
			),
		);
		if ( $settings['link'] === 'photo' ) {
			$ret['link_image_size'] = array(
				'label' => __( 'Linked image size', 'directories-pro' ),
				'value' => $this->_getLinkedImageSizeOptions()[ $settings['link_image_size'] ],
			);
		}
		if ( $field->getFieldMaxNumItems() !== 1 ) {
			$ret['cols'] = array(
				'label' => __( 'Number of columns', 'directories-pro' ),
				'value' => $settings['cols'],
			);
		}

		return $ret;
	}
}
