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

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

class PostCountFieldType extends Field\Type\AbstractType implements
	Field\Type\ISortable,
	Field\Type\IQueryable,
	Field\Type\IColumnable {

	protected function _fieldTypeInfo() {
		return array(
			'label'         => 'Post Count',
			'entity_types'  => array( 'user' ),
			'creatable'     => false,
			'max_num_items' => 0,
		);
	}

	public function fieldTypeSchema( array $settings = array() ) {
		return array(
			'columns' => array(
				'value'            => array(
					'type'     => Application::COLUMN_INTEGER,
					'notnull'  => true,
					'unsigned' => true,
					'was'      => 'value',
					'default'  => 0,
				),
				'post_bundle_type' => array(
					'type'    => Application::COLUMN_VARCHAR,
					'notnull' => true,
					'length'  => 40,
					'was'     => 'post_bundle_type',
					'default' => '',
				),
				'post_bundle_name' => array(
					'type'    => Application::COLUMN_VARCHAR,
					'notnull' => true,
					'length'  => 40,
					'was'     => 'post_bundle_name',
					'default' => '',
				),
				'lang'             => array(
					'type'    => Application::COLUMN_VARCHAR,
					'notnull' => true,
					'length'  => 5,
					'was'     => 'lang',
					'default' => '',
				),
			),
			'indexes' => array(
				'value'            => array(
					'fields' => array( 'value' => array( 'sorting' => 'ascending' ) ),
					'was'    => 'value',
				),
				'post_bundle_type' => array(
					'fields' => array( 'post_bundle_type' => array( 'sorting' => 'ascending' ) ),
					'was'    => 'post_bundle_type',
				),
				'post_bundle_name' => array(
					'fields' => array( 'post_bundle_name' => array( 'sorting' => 'ascending' ) ),
					'was'    => 'post_bundle_name',
				),
				'lang'             => array(
					'fields' => array( 'lang' => array( 'sorting' => 'ascending' ) ),
					'was'    => 'lang',
				),
			),
		);
	}

	public function fieldTypeOnSaveValues( IField $field, array $values, ?array $currentValues = null, array &$extraArgs = array() ) {
		$ret = array();
		foreach ( $values as $value ) {
			if ( ! is_array( $value )
				|| empty( $value['value'] )
				|| empty( $value['post_bundle_type'] )
				|| empty( $value['post_bundle_name'] )
			) {
				$ret[] = false; // delete
			} else {
				$ret[] = $value;
			}
		}
		return $ret;
	}

	public function fieldTypeOnLoadValues( IField $field, array &$values, IEntity $entity, array $allValues ) {
		$new_values = array();
		foreach ( $values as $value ) {
			$new_values[0][ $value['post_bundle_type'] ][ $value['post_bundle_name'] ][ $value['lang'] ] = (int) $value['value'];
		}
		$values = $new_values;
	}

	public function fieldTypeIsModified( IField $field, $valueToSave, $currentLoadedValue ) {
		$current = $new = array();
		if ( ! empty( $currentLoadedValue[0] ) ) {
			foreach ( array_keys( $currentLoadedValue[0] ) as $bundle_type ) {
				foreach ( array_keys( $currentLoadedValue[0][ $bundle_type ] ) as $bundle_name ) {
					foreach ( array_keys( $currentLoadedValue[0][ $bundle_type ][ $bundle_name ] ) as $lang ) {
						$current[] = array(
							'value'            => (int) $currentLoadedValue[0][ $bundle_type ][ $bundle_name ][ $lang ],
							'post_bundle_type' => $bundle_type,
							'post_bundle_name' => $bundle_name,
							'lang'             => $lang,
						);
					}
				}
			}
		}
		foreach ( $valueToSave as $value ) {
			$new[] = array(
				'value'            => (int) $value['value'],
				'post_bundle_type' => $value['post_bundle_type'],
				'post_bundle_name' => $value['post_bundle_name'],
				'lang'             => $value['lang'],
			);
		}
		return $current !== $new;
	}

	public function fieldSortableOptions( IField $field ) {
		$ret = array();
		foreach ( array_keys( $this->_application->getComponent( 'User' )->getPublicPostBundles() ) as $bundle_name ) {
			if ( ! $post_bundle = $this->_application->Entity_Bundle( $bundle_name ) ) {
				continue;
			}

			$ret[] = array(
				'label' => sprintf( _x( 'Most %s', 'sort option label', 'directories-pro' ), $post_bundle->getLabel() ),
				'args'  => array( $post_bundle->name ),
			);
			$ret[] = array(
				'label' => sprintf( _x( 'Least %s', 'sort option label', 'directories-pro' ), $post_bundle->getLabel() ),
				'args'  => array( $post_bundle->name, 'asc' ),
			);
		}

		return empty( $ret ) ? false : $ret;
	}

	public function fieldSortableSort( Query $query, $fieldName, ?array $args = null ) {
		if ( ! isset( $args[0] ) ) {
			return;
		}

		$query->fieldIs( $fieldName, $args[0], 'post_bundle_name' );
		if ( $lang = $this->_application->getPlatform()->getCurrentLanguage() ) {
			$query->fieldIs( $fieldName, $lang, 'lang' );
		}
		$query->sortByField( $fieldName, isset( $args[1] ) && $args[1] === 'asc' ? 'ASC' : 'DESC', 'value', null, 0 );
	}

	public function fieldQueryableInfo( Field\IField $field, $inAdmin = false ) {
		return array(
			'example' => 'directory_ltg_ltg,5',
			'tip'     => __( 'Enter a post type name and a minimum post count number or two numbers separated with a comma for range search.', 'directories-pro' ),
		);
	}

	public function fieldQueryableQuery( Query $query, $fieldName, $paramStr, Bundle $bundle ) {
		$params = $this->_queryableParams( $paramStr );
		if ( ! empty( $params[1] ) || ! empty( $params[2] ) ) {
			$query->fieldIs( $fieldName, $params[0], 'post_bundle_name' );
			if ( $lang = $this->_application->getPlatform()->getCurrentLanguage() ) {
				$query->fieldIs( $fieldName, $lang, 'lang' );
			}
			if ( ! empty( $params[1] ) ) {
				$query->fieldIsOrGreaterThan( $fieldName, $params[1] );
			}
			if ( ! empty( $params[2] ) ) {
				$query->fieldIsOrSmallerThan( $fieldName, $params[2] );
			}
		}
	}

	public function fieldColumnableInfo( IField $field ) {
		$ret = array();
		foreach ( array_keys( $this->_application->getComponent( 'User' )->getPublicPostBundles() ) as $bundle_name ) {
			if ( ! $post_bundle = $this->_application->Entity_Bundle( $bundle_name ) ) {
				continue;
			}

			$ret[ $bundle_name ] = array(
				'label'  => $post_bundle->getGroupLabel() . ' - ' . $post_bundle->getLabel(),
				'hidden' => true,
			);
		}
		return $ret;
	}

	public function fieldColumnableColumn( IField $field, IEntity $entity, $column = '' ) {
		if ( ( ! $values = $entity->getFieldValue( $field->getFieldName() ) )
			|| empty( $values[0] )
			|| ( ! $post_bundle = $this->_application->Entity_Bundle( $column ) )
		) {
			return 0;
		}

		$lang  = $this->_application->getPlatform()->getCurrentLanguage();
		$count = empty( $values[0][ $post_bundle->type ][ $post_bundle->name ][ $lang ] ) ? 0 : (int) $values[0][ $post_bundle->type ][ $post_bundle->name ][ $lang ];
		if ( ! $count
			|| ( ! $url = $this->_application->getPlatform()->getEntityAdmninUrl( $post_bundle->entitytype_name, $post_bundle->name, null, $entity->getId() ) )
		) {
			return $count;
		}

		return '<a href="' . $this->_application->H( $url ) . '">' . $count . '</a>';
	}
}
