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

use SabaiApps\Directories\Application;
use SabaiApps\Directories\Component\Entity\Model\Bundle;

class UtilHelper {

	public function runCron( Application $application, &$logs ) {
		// Un-feature entities
		foreach ( $application->Entity_BundleTypes_byFeatures( array( 'featurable' ) ) as $entity_type => $bundle_types ) {
			$entities = $application->Entity_Query( $entity_type )
				->fieldIsIn( 'bundle_type', $bundle_types )
				->fieldIsOrSmallerThan( 'entity_featured', time(), 'expires_at' )
				->fieldIsGreaterThan( 'entity_featured', 0, 'expires_at' ) // exclude those that never expire
				->fetch();
			foreach ( array_keys( $entities ) as $entity_id ) {
				$application->Entity_Save( $entities[ $entity_id ], array( 'entity_featured' => false ) );
				$logs['success'][] = sprintf( __( 'Unfeatured item: %s', 'directories-pro' ), $entities[ $entity_id ]->getTitle() );
			}
			$application->Action( 'entity_entities_unfeatured', array( $entity_type, $entities, &$logs ) );
		}

		// Expire entities
		if ( $application->Entity_Storage()->getFieldSchemaType( 'entity_expires' ) ) { // @Todo: Do not require field schema check
			foreach ( $application->Entity_BundleTypes_byFeatures( array( 'expirable' ) ) as $entity_type => $bundle_types ) {
				foreach ( $application->Entity_Bundles_byType( $bundle_types ) as $bundle ) {
					if ( empty( $bundle->info['entity_expire'] ) ) {
						continue;
					}

					$expiration_field = 'entity_expires';
					if ( $custom_expiry_date_field = $this->hasCustomExpiryDateField( $application, $bundle ) ) {
						$expiration_field = $custom_expiry_date_field->getFieldName();
					}
					$query = $application->Entity_Query( $entity_type, $bundle->name )
						->fieldIs( 'status', $application->Entity_Status( $bundle->entitytype_name, 'publish' ) )
						->fieldIsOrSmallerThan( $expiration_field, time() );
					if ( ! empty( $bundle->info['payment_enable'] )
						&& $application->isComponentLoaded( 'Payment' )
					) {
						$query->fieldIsNull( 'payment_plan', 'plan_id' );
					}
					if ( ! $entities = $query->fetch() ) {
						continue;
					}

					$values                   = array();
					$status                   = $application->Filter( 'entity_expired_status', isset( $bundle->info['entity_expire_status'] ) ? $bundle->info['entity_expire_status'] : 'trash', array( $bundle ) );
					$values['entity_expires'] = false;
					if ( is_array( $status ) ) {
						$values['status'] = $status[0];
						if ( isset( $status[1] ) ) {
							if ( $status[1] === true ) {
								if ( ! empty( $bundle->info['entity_expire_days'] ) ) {
									$values['entity_expires'] = time() + 86400 * $bundle->info['entity_expire_days'];
								}
							} elseif ( $status[1] !== false ) {
								if ( ( is_int( $status[1] ) && $status[1] > time() )
										|| ( $status[1] = $application->System_Date_strToTime( $status[1] ) )
									) {
									$values['entity_expires'] = $status[1];
								}
							}
						}
					} else {
						$values['status'] = $application->Entity_Status( $bundle->entitytype_name, $status );
					}
					if ( $expiration_field !== 'entity_expires' ) {
						$values[ $expiration_field ] = $values['entity_expires'];
					}
					foreach ( array_keys( $entities ) as $entity_id ) {
						$application->Entity_Save( $entities[ $entity_id ], $values );
						$logs['success'][] = sprintf(
							__( 'Expired: %1$s (%2$s)', 'directories-pro' ),
							$entities[ $entity_id ]->getTitle(),
							$bundle->getGroupLabel() . ' - ' . $bundle->getLabel( 'singular' )
						);
					}

					// Expire referenced/referencing entities?
					if ( ! empty( $bundle->info['entity_expire_ref'] )
						&& ! empty( $bundle->info['entity_expire_ref_bundles'] )
					) {
						foreach ( $bundle->info['entity_expire_ref_bundles'] as $bundle_ref ) {
							if ( strpos( $bundle_ref, ',' ) ) {
								// Get referenced entities
								list($ref_bundle_name, $ref_field_name) = explode( ',', $bundle_ref );
								$ref_bundle                             = $application->Entity_Bundle( $ref_bundle_name, '', true );
								$ref_entities                           = $application->Entity_Query( $ref_bundle->entitytype_name )
									->fieldIs( 'bundle_name', $ref_bundle->name )
									->fieldIsIn( $ref_field_name, array_keys( $entities ) )
									->fetch();
							} else {
								// Get referencing entities
								$ref_field_name = $bundle_ref;
								$ref_entity_ids = array();
								foreach ( array_keys( $entities ) as $entity_id ) {
									foreach ( $entities[ $entity_id ]->getFieldValue( $ref_field_name ) as $ref_entity_id ) {
										$ref_entity_ids[] = is_object( $ref_entity_id ) ? $ref_entity_id->getId() : $ref_entity_id;
									}
								}
								if ( empty( $ref_entity_ids ) ) {
									continue;
								}

								if ( ! $ref_field = $application->Entity_Field( $bundle, $bundle_ref ) ) {
									continue;
								}

								$ref_field_settings = $ref_field->getFieldSettings();
								if ( empty( $ref_field_settings['bundle'] ) ) {
									continue;
								}

								$ref_bundle   = $application->Entity_Bundle( $ref_field_settings['bundle'], '', true );
								$ref_entities = $application->Entity_Query( $ref_bundle->entitytype_name )
									->fieldIs( 'bundle_name', $ref_bundle->name )
									->fieldIsIn( 'id', $ref_entity_ids )
									->fetch();
							}
							if ( ! empty( $ref_entities ) ) {
								foreach ( array_keys( $ref_entities ) as $entity_id ) {
									$application->Entity_Save( $ref_entities[ $entity_id ], $values );
									$logs['success'][] = sprintf(
										__( 'Expired: %1$s (%2$s)', 'directories-pro' ),
										$ref_entities[ $entity_id ]->getTitle(),
										$ref_bundle->getGroupLabel() . ' - ' . $ref_bundle->getLabel( 'singular' )
									);
								}
							}
						}
					}

					// Notify
					$application->Action( 'entity_entities_expired', array( $bundle, $entities, $values, &$logs ) );
				}
			}
		}
	}

	public function hasCustomExpiryDateField( Application $application, Bundle $bundle ) {
		if ( ! empty( $bundle->info['entity_expire'] ) ) {
			if ( ! empty( $bundle->info['entity_expire_field'] ) ) {
				if ( $field = $application->Entity_Field( $bundle, $bundle->info['entity_expire_field'] ) ) {
					return $field;
				}

				$application->logError( sprintf( __( 'Expiry date field %s does not exist.', 'directories-pro' ), $bundle->info['entity_expire_field'] ) );
			}
		}
		return false;
	}
}
