<?php
namespace SabaiApps\Directories\Component\Payment\NotificationEvent;

use SabaiApps\Directories\Exception;

class PlanExpiringNotificationEvent extends AbstractEntityNotificationEvent {

	protected function _notificationEntityEventInfo() {
		return array(
			'label'            => _x( 'Payment plan expiring', 'notification event', 'directories-pro' ) . ' - %s',
			'default_settings' => array(
				'stop_after' => null,
			),
			'actions'          => array(
				'payment_entity_expiring',
			),
			'weight'           => 24,
			'testable'         => true,
		);
	}

	public function notificationEventSettingsForm( array $settings, array $parents = array() ) {
		return parent::notificationEventSettingsForm( $settings, $parents ) + array(
			'stop_after' => array(
				'#type'          => 'slider',
				'#title'         => __( 'Stop sending after X days', 'directories-pro' ),
				'#integer'       => true,
				'#min_value'     => 0,
				'#max_value'     => $expiring_days = $this->_application->getComponent( 'Payment' )->getConfig( 'plan', 'expiring_days' ),
				'#horizontal'    => true,
				'#default_value' => isset( $settings['stop_after'] ) ? $settings['stop_after'] : $expiring_days,
			),
		);
	}

	public function notificationEventMessages( array $settings, array $params ) {
		if ( ! $entity = $this->_application->Entity_Entity( $params[0], $params[1] ) ) {
			return array();
		}

		$expiring_remaining = null;
		$expiring_days      = $this->_application->getComponent( 'Payment' )->getConfig( 'plan', 'expiring_days' );
		if ( $expiring_days > 1
			&& ! empty( $settings['stop_after'] )
			&& $settings['stop_after'] < $expiring_days
		) {
			// Remaining time must be more than [expiring_days - X] days if notifying limited times
			$expiring_remaining = 86400 * ( $expiring_days - $settings['stop_after'] );
		}

		return new PostExpiringNotificationEventIterator( $this->_getMessageIterator( array( $entity ), $settings ), $expiring_remaining );
	}

	protected function _getDefaultNotificationLabel() {
		return sprintf(
			__( 'Your %s is about to expire', 'directories-pro' ),
			strtolower( $singular = $this->_getContentTypeLabel() ),
			$singular
		);
	}

	protected function _getDefaultNotificationBody() {
		return array(
			sprintf(
				__( 'The following %1$s posted on our site will expire in %2$s day(s).', 'directories-pro' ),
				strtolower( $singular = $this->_getContentTypeLabel() ),
				'%payment_expire_days%',
				$singular
			),
			'%title%' . PHP_EOL . '%permalink_url%',
			sprintf( __( 'You can renew the %1$s from the dashboard page on our site.', 'directories-pro' ), strtolower( $singular ), $singular ) . PHP_EOL . '%dashboard_url%',
		);
	}

	protected function _getQueryEntitiesUrl( array $settings, $status = null, $num = 5 ) {
		return $this->_application->MainUrl(
			'/_drts/entity/' . $this->_bundleType . '/query_payment_entities',
			$this->_getQueryEntitiesParams( $settings, $status, $num ) + array( 'payment_plan' => 2 ),
			'',
			'&'
		);
	}

	public function notificationEventParams( array $settings, array $paramSettings ) {
		if ( ! $entity = $this->_application->Entity_Entity( 'post', $paramSettings['entity'] ) ) {
			throw new Exception\RuntimeException( 'Failed fetching post. ID: ' . $paramSettings['entity'] );
		}
		$params[1] = array( $entity );
		return $params;
	}
}

class PostExpiringNotificationEventIterator implements \Iterator {

	protected $_iterator, $_remainingDays;

	public function __construct( EntityNotificationEventMessageIterator $iterator, $remainingDays = null ) {
		$this->_iterator      = $iterator;
		$this->_remainingDays = (int) $remainingDays;
	}

	#[\ReturnTypeWillChange]
	public function next() {
		$this->_iterator->next();
	}

	#[\ReturnTypeWillChange]
	public function valid() {
		if ( empty( $this->_remainingDays ) ) {
			return $this->_iterator->valid();
		}

		while ( $this->_iterator->valid() ) {
			if ( $this->_iterator->current()['entity']->getSingleFieldValue( 'payment_plan', 'expires_at' ) - time() > $this->_remainingDays ) {
				return true;
			}
		}

		return false;
	}

	#[\ReturnTypeWillChange]
	public function current() {
		return $this->_iterator->current();
	}

	#[\ReturnTypeWillChange]
	public function key() {
		return $this->_iterator->key();
	}

	#[\ReturnTypeWillChange]
	public function rewind() {
		$this->_iterator->rewind();
	}
}
