<?php
namespace SabaiApps\Directories\Component\Faker\Generator;

use SabaiApps\Directories\Component\Field\IField;
use SabaiApps\Directories\Exception;
use SabaiApps\Directories\Component\Form\Form;
use SabaiApps\Directories\Component\Entity\Type\IEntity;

class PexelsPhotoGenerator extends AbstractGenerator {

	protected function _fakerGeneratorInfo() {
		return array(
			'label'            => __( 'Pexels Photo Generator', 'directories-pro' ),
			'description'      => __( 'Download photos from https://pexels.com/ based on keywords.', 'directories-pro' ),
			'field_types'      => array( 'wp_image' ),
			'add_probability'  => true,
			'default_settings' => array(
				'max' => 5,
			),
		);
	}

	public function fakerGeneratorSettingsForm( IField $field, array $settings, $mode, array $parents = array() ) {
		$form = array(
			'api_key'     => array(
				'#type'                  => 'textfield',
				'#title'                 => __( 'Pexels API key', 'directories-pro' ),
				'#description'           => sprintf(
					$this->_application->H( __( 'Get API key from %s.', 'directories-pro' ) ),
					'<a href="https://www.pexels.com/api/key/" target="_blank" rel="nofollow">Pexels</a>'
				) . ' According to Pexels API guidelines, you must include a prominent link to Pexels when using photos from their API.
You can use a text link such as “Photos provided by Pexels” or their official logo.',
				'#description_no_escape' => true,
				'#required'              => function ( $form ) use ( $parents ) {
					return $form->getValue( array_merge( array_slice( $parents, 0, -2 ), array( 'generator' ) ) ) === 'pexels_photos';
				},
				'#default_value'         => ( $api_key = $this->_application->getPlatform()->getEntityMeta( 'user', $this->_application->getUser()->id, 'faker_pexels_photos_api_key' ) ) ? $api_key : null,
				'#element_validate'      => array(
					function ( Form $form, &$value ) {
						if ( empty( $value ) ) {
							return;
						}
						$this->_application->getPlatform()->setEntityMeta( 'user', $this->_application->getUser()->id, 'faker_pexels_photos_api_key', $value );
					},
				),
			),
			'query'       => array(
				'#type'          => 'textfield',
				'#title'         => __( 'Search Keyword', 'directories-pro' ),
				'#description'   => __( 'Enter a keyword to search for photos on Pexels.', 'directories-pro' ),
				'#default_value' => null,
				'#placeholder'   => __( 'e.g., Nature, Technology, People', 'directories-pro' ),
			),
			'color'       => array(
				'#type'          => 'colorpicker',
				'#title'         => __( 'Color Filter', 'directories-pro' ),
				'#description'   => __( 'Select a color to filter photos by color.', 'directories-pro' ),
				'#default_value' => null,
			),
			'orientation' => array(
				'#type'          => 'select',
				'#title'         => __( 'Orientation', 'directories-pro' ),
				'#options'       => array(
					''          => __( 'Any', 'directories-pro' ),
					'landscape' => __( 'Landscape', 'directories-pro' ),
					'portrait'  => __( 'Portrait', 'directories-pro' ),
					'square'    => __( 'Square', 'directories-pro' ),
				),
				'#default_value' => '',
			),
			'max'         => $this->_getMaxNumItemsSettingForm( $field, $settings['max'] ),
		);
		if ( $mode !== 'new' ) {
			$form['preserve_existing'] = array(
				'#type'          => 'checkbox',
				'#title'         => __( 'Preserve existing', 'directories-pro' ),
				'#description'   => __( 'If checked, existing photos will be preserved and new photos will be added to them.', 'directories-pro' ),
				'#default_value' => true,
			);
		}
		return $form;
	}

	public function fakerGeneratorGenerate( IField $field, array $settings, array &$formStorage, ?IEntity $entity = null ) {
		if ( ! isset( $formStorage['pexels_photos'] ) ) {
			try {
				$params = array(
					'query'       => empty( $settings['query'] ) ? 'nature' : $settings['query'],
					'per_page'    => 80,
					'color'       => ! empty( $settings['color'] ) ? $settings['color'] : null,
					'orientation' => ! empty( $settings['orientation'] ) ? $settings['orientation'] : null,
				);
				$url    = 'https://api.pexels.com/v1/search';
				$result = $this->_application->getPlatform()->remoteGet(
					$this->_application->Url( $url, $params, '', '&' ),
					array(
						'headers' => array(
							'Authorization' => $settings['api_key'],
							'Accept'        => 'application/json',
							'Cache-Control' => 'no-cache',
						),
					)
				);
				if ( ! $pexels_photos = json_decode( $result, true ) ) {
					throw new Exception\RuntimeException( 'Failed decoding photo list JSON return from Pexels API.' );
				}
				$formStorage['pexels_photos'] = (array) $pexels_photos['photos'];
			} catch ( \Exception $e ) {
				$this->_application->logError( $e );
				return false;
			}
		}

		if ( ! isset( $formStorage['pexels_photos_downloaded'] ) ) {
			$formStorage['pexels_photos_downloaded'] = array();
		}

		$ret       = array();
		$num       = $this->_getMaxNumItems( $field, $settings['max'] );
		$max_index = count( $formStorage['pexels_photos'] ) - 1;
		$i         = 0;
		do {
			++$i;
			$index = mt_rand( 0, $max_index );
			$photo = $formStorage['pexels_photos'][ $index ];
			if ( isset( $ret[ $photo['id'] ] ) ) {
				continue;
			}

			if ( ! isset( $formStorage['pexels_photos_downloaded'][ $photo['id'] ] ) ) {
				$url = $photo['src']['original'];
				try {
					$file_path = $this->_application->getPlatform()->downloadUrl( $url );
				} catch ( \Exception $e ) {
					$this->_application->logError( $e );
					continue;
				}

				try {
					$file = $this->_application->getPlatform()->uploadFile(
						$file_path,
						'pexels-photo-' . $photo['id'] . '.png',
						$photo['alt'],
						sprintf( '"%s" by %s', $photo['alt'], $photo['photographer'] )
					);
				} catch ( \Exception $e ) {
					@unlink( $file_path );
					$this->_application->logError( $e );
					continue;
				}

				$formStorage['pexels_photos_downloaded'][ $photo['id'] ] = $file;
			}

			$ret[ $photo['id'] ] = $formStorage['pexels_photos_downloaded'][ $photo['id'] ];

		} while ( count( $ret ) < $num && $i < $num + 5 );

		$ret = array_values( $ret );

		if ( isset( $entity )
			&& ! empty( $settings['preserve_existing'] )
			&& ( $current_photos = $entity->getFieldValue( $field->getFieldName() ) )
		) {
			foreach ( $current_photos as $photo ) {
				$ret[] = $photo;
			}
		}

		return $ret;
	}
}
