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

use SabaiApps\Directories\Component\Field;
use SabaiApps\Directories\Application;
use SabaiApps\Directories\Component\Entity\Model\Bundle;
use SabaiApps\Directories\Component\Entity\Type\IEntity;
use SabaiApps\Directories\Component\Entity\FieldType\IPersonalDataAuthorFieldType;
use SabaiApps\Framework\Application\HttpRequest;

class GuestFieldType extends Field\Type\AbstractType implements
	Field\Type\IHumanReadable,
	Field\Type\IPersonalData,
	Field\Type\ICopiable,
	Field\Type\IQueryable,
	IPersonalDataAuthorFieldType,
	Field\Type\IEmail,
	Field\Type\IColumnable {

	protected function _fieldTypeInfo() {
		return array(
			'label'                              => __( 'Guest Author', 'directories-pro' ),
			'description'                        => __( 'Field for gathering guest user details to proceed with the submission.', 'directories-pro' ),
			'creatable'                          => false,
			'disablable'                         => false,
			'requirable'                         => false,
			'icon'                               => 'fas fa-person-circle-question',
			'display_element_can_admin_only'     => false,
			'display_element_can_hide_on_parent' => false,
			'admin_only'                         => true,
		);
	}

	public function fieldTypeSchema( array $settings = array() ) {
		return array(
			'columns' => array(
				'email'        => array(
					'type'    => Application::COLUMN_VARCHAR,
					'notnull' => true,
					'length'  => 255,
					'was'     => 'email',
					'default' => '',
				),
				'name'         => array(
					'type'    => Application::COLUMN_VARCHAR,
					'notnull' => true,
					'length'  => 255,
					'was'     => 'name',
					'default' => '',
				),
				'url'          => array(
					'type'    => Application::COLUMN_VARCHAR,
					'notnull' => true,
					'length'  => 255,
					'was'     => 'url',
					'default' => '',
				),
				'guid'         => array(
					'type'    => Application::COLUMN_VARCHAR,
					'notnull' => true,
					'length'  => 23,
					'was'     => 'guid',
					'default' => '',
				),
				'guid_created' => array(
					'type'     => Application::COLUMN_INTEGER,
					'unsigned' => true,
					'notnull'  => true,
					'length'   => 10,
					'default'  => 0,
				),
				'ip_hash'      => array(
					'type'    => Application::COLUMN_VARCHAR,
					'notnull' => true,
					'length'  => 64,
					'was'     => 'ip_hash',
					'default' => '',
				),
			),
		);
	}

	public function fieldTypeOnSaveValues( Field\IField $field, array $values, ?array $currentValues = null, array &$extraArgs = array() ) {
		if ( ! $this->_application->getPlatform()->isAdmin()
			|| ! $this->_application->getUser()->isAdministrator()
		) {
			// Only guest users can add new values
			if ( is_null( $currentValues )
				&& ! $this->_application->getUser()->isAnonymous()
			) {
				return false;
			}
		}

		$ip  = $this->_application->getUser()->isAnonymous() ? HttpRequest::ip() : '0.0.0.0';
		$ret = array();
		foreach ( $values as $key => $value ) {
			if ( is_array( $value ) ) {
				if ( ! empty( $currentValues[ $key ] ) ) {
					$value += $currentValues[ $key ];
				}
				if ( empty( $value['guid'] ) ) {
					$value['guid']         = uniqid( '', true );
					$value['guid_created'] = time();
				}
				if ( empty( $value['ip_hash'] )
					|| ! is_string( $value['ip_hash'] )
					|| strlen( $value['ip_hash'] ) !== 64
				) {
					$value['ip_hash'] = $this->_application->getPlatform()->getHash( $ip );
				}
				$ret[] = $value;
			} elseif ( $value === false ) { // deleting explicitly?
				$ret[] = false;
			}
		}
		return empty( $ret ) ? false : $ret;
	}

	public function fieldHumanReadableText( Field\IField $field, IEntity $entity, $separator = null, $key = null ) {
		if ( ! $value = $entity->getSingleFieldValue( $field->getFieldName() ) ) {
			return '';
		}

		$ret = array();
		foreach ( array( 'name', 'email', 'url' ) as $key ) {
			if ( ! isset( $value[ $key ] )
				|| ! strlen( $value[ $key ] )
			) {
				continue;
			}

			$ret[] = $value[ $key ];
		}

		return implode( ' - ', $ret );
	}

	public function fieldPersonalDataExport( Field\IField $field, IEntity $entity ) {
		if ( ! $value = $entity->getSingleFieldValue( $field->getFieldName() ) ) {
			return;
		}

		$ret = array();
		foreach ( array(
			'name'    => __( 'Guest Name', 'directories-pro' ),
			'email'   => __( 'E-mail Address', 'directories-pro' ),
			'url'     => __( 'Website URL', 'directories-pro' ),
			'ip_hash' => __( 'IP Address', 'directories-pro' ),
		) as $key => $name ) {
			if ( ! strlen( $value[ $key ] ) ) {
				continue;
			}

			$ret[ $key ] = array(
				'name'  => $name,
				'value' => $value[ $key ],
			);
		}
		return $ret;
	}

	public function fieldPersonalDataErase( Field\IField $field, IEntity $entity ) {
		return true; // delete
	}

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

	public function fieldPersonalDataAnonymize( Field\IField $field, IEntity $entity ) {
		$value = $entity->getSingleFieldValue( $field->getFieldName() );
		return array(
			'name'    => $this->_application->getPlatform()->anonymizeText( $value['name'] ),
			'email'   => $this->_application->getPlatform()->anonymizeEmail( $value['email'] ),
			'url'     => strlen( $value['url'] ) ? $this->_application->getPlatform()->anonymizeUrl( $value['url'] ) : '',
			'ip_hash' => $this->_application->getPlatform()->getHash( '0.0.0.0' ),
		);
	}

	public function fieldCopyValues( Field\IField $field, array $values, array &$allValue, $lang = null ) {
		return $values;
	}

	public function fieldQueryableInfo( Field\IField $field, $inAdmin = false ) {
		return array(
			'example' => 'example@domain.com',
			'tip'     => __( 'Enter e-mail addresses separated by a comma.', 'directories-pro' ),
		);
	}

	public function fieldQueryableQuery( Field\Query $query, $fieldName, $paramStr, Bundle $bundle ) {
		if ( ! $emails = $this->_queryableParams( $paramStr ) ) {
			return;
		}

		$query->fieldIsIn( $fieldName, $emails, 'email' );
	}

	public function fieldEmailAddress( Field\IField $field, IEntity $entity, $single = true ) {
		if ( ! $email = $entity->getSingleFieldValue( $field->getFieldName(), 'email' ) ) {
			return $single ? null : array();
		}

		return $single ? $email : array( $email );
	}

	public function fieldColumnableInfo( Field\IField $field ) {
		return array(
			'' => array(
				'label'  => $field->getFieldLabel(),
				'sortby' => 'name',
			),
		);
	}

	public function fieldColumnableColumn( Field\IField $field, IEntity $entity, $column = '' ) {
		if ( ! $value = $entity->getSingleFieldValue( $field->getFieldName() ) ) {
			return;
		}

		$labels = array();
		foreach ( array( 'name', 'email', 'url' ) as $key ) {
			if ( ! isset( $value[ $key ] )
				|| ! strlen( $value[ $key ] )
			) {
				continue;
			}

			$labels[] = $value[ $key ];
		}
		if ( empty( $labels ) ) {
			return;
		}

		$label = array_shift( $labels );
		if ( ! empty( $labels ) ) {
			$label = sprintf( __( '%1$s (%2$s)', 'directories-pro' ), $label, implode( ', ', $labels ) );
		}
		return $this->_application->H( $label );
	}
}
