<?php
namespace SabaiApps\Directories\Component\Entity\FieldType;

use SabaiApps\Directories\Component\Field\Type\AbstractType;
use SabaiApps\Directories\Component\Field\IField;
use SabaiApps\Directories\Component\Field\Query;
use SabaiApps\Directories\Component\Entity\Type\IEntity;
use SabaiApps\Directories\Component\Field\Type\IConditionable;
use SabaiApps\Directories\Component\Field\Type\IHumanReadable;
use SabaiApps\Directories\Component\Field\Type\IQueryable;
use SabaiApps\Directories\Component\Field\Type\ISchemable;
use SabaiApps\Directories\Component\Field\Type\IPersonalData;
use SabaiApps\Directories\Component\Field\Type\QueryableUserTrait;
use SabaiApps\Directories\Component\Field\Type\IComparable;

class AuthorFieldType extends AbstractType implements
	ISchemable,
	IQueryable,
	IHumanReadable,
	IPersonalDataAuthorFieldType,
	IPersonalData,
	IConditionable,
	IComparable {

	use QueryableUserTrait;

	protected function _fieldTypeInfo() {
		return array(
			'label'        => __( 'Author', 'directories-pro' ),
			'icon'         => 'fas fa-user',
			'admin_only'   => true,
			'entity_types' => array( 'post' ),
		);
	}

	public function fieldSchemaProperties( IField $field ) {
		return array( 'author' );
	}

	public function fieldSchemaRenderProperty( IField $field, $property, IEntity $entity ) {
		return array(
			array(
				'@type' => 'Person',
				'name'  => $this->_application->Entity_Author( $entity )->name,
			),
		);
	}

	public function fieldHumanReadableText( IField $field, IEntity $entity, $separator = null, $key = null ) {
		return $this->_application->Entity_Author( $entity )->name;
	}

	public function fieldPersonalDataQuery( Query $query, $fieldName, $email, $userId ) {
		$query->fieldIs( $fieldName, $userId );
	}

	public function fieldPersonalDataAnonymize( IField $field, IEntity $entity ) {
		return 0;
	}

	public function fieldConditionableInfo( IField $field, $isServerSide = false ) {
		if ( ! $isServerSide ) {
			return;
		}

		return array(
			'' => array(
				'compare' => array( 'value', '!value', 'one', 'empty', 'filled' ),
				'tip'     => __( 'Enter user IDs, usernames, and/or "_current_user_" separated with commas.', 'directories-pro' ),
				'example' => 7,
			),
		);
	}

	public function fieldConditionableRule( IField $field, $compare, $value = null, $name = '' ) {
		switch ( $compare ) {
			case 'value':
			case '!value':
			case 'one':
				$value = trim( $value );
				if ( strpos( $value, ',' ) ) {
					if ( ! $value = explode( ',', $value ) ) {
						return;
					}

					$value = array_map( 'trim', $value );
				} else {
					$value = array( $value );
				}
				foreach ( array_keys( $value ) as $k ) {
					if ( $value[ $k ] === '_current_user_' ) {
						$value[ $k ] = (int) $this->_application->getUser()->id;
					} elseif ( ! is_numeric( $value[ $k ] ) ) {
						if ( ! $user = $this->_application->getPlatform()->getUserIdentityFetcher()->fetchByUsername( $value[ $k ] ) ) {
							unset( $value[ $k ] ); // invalid username
							continue;
						}
						$value[ $k ] = (int) $user->id;
					} else {
						$value[ $k ] = (int) $value[ $k ];
					}
				}
				return array(
					'type'  => $compare,
					'value' => $value,
				);
			case 'empty':
				return array(
					'type'  => 'filled',
					'value' => false,
				);
			case 'filled':
				return array(
					'type'  => 'empty',
					'value' => false,
				);
			default:
				return;
		}
	}

	public function fieldConditionableMatch( IField $field, array $rule, array $values, IEntity $entity ) {
		$author_id = (int) $entity->getAuthorId();
		switch ( $rule['type'] ) {
			case 'value':
			case '!value':
			case 'one':
				if ( empty( $values ) ) {
					return $rule['type'] === '!value';
				}

				foreach ( (array) $rule['value'] as $rule_value ) {
					if ( $author_id === $rule_value ) {
						if ( $rule['type'] === '!value' ) {
							return false;
						}
						if ( $rule['type'] === 'one' ) {
							return true;
						}
						continue;
					}
					// One of rules did not match
					if ( $rule['type'] === 'value' ) {
						return false;
					}
				}
				// All rules matched or did not match.
				return $rule['type'] !== 'one' ? true : false;
			case 'empty':
				return empty( $author_id ) === $rule['value'];
			case 'filled':
				return ! empty( $author_id ) === $rule['value'];
			default:
				return false;
		}
	}

	public function fieldPersonalDataExport( IField $field, IEntity $entity ) {
	}

	public function fieldPersonalDataErase( IField $field, IEntity $entity ) {
		return 0;
	}

	public function fieldComparableItemLabels( IField $field ) {
		return array( '' => (string) $field->getFieldLabel() );
	}

	public function fieldComparableItemValues( IField $field, IEntity $entity, $html = true ) {
		if ( ! $html ) {
			return $this->fieldHumanReadableText( $field, $entity );
		}

		return array( '' => $this->_application->UserIdentityHtml( $this->_application->Entity_Author( $entity ), 'link_thumb_s' ) );
	}
}
