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

use SabaiApps\Directories\Application;
use SabaiApps\Directories\Component\Contact\Form\IForm;
use SabaiApps\Directories\Component\Entity\Type\IEntity;
use SabaiApps\Directories\Component\Field\Type\IEmail;
use SabaiApps\Directories\Exception;

class FormsHelper {

	private $_impls = array();

	public function help( Application $application, $useCache = true ) {
		if ( ! $useCache
			|| ( ! $forms = $application->getPlatform()->getCache( 'contact_forms' ) )
		) {
			$forms = array();
			foreach ( $application->InstalledComponentsByInterface( 'Contact\IForms' ) as $component_name ) {
				if ( ! $application->isComponentLoaded( $component_name ) ) {
					continue;
				}

				foreach ( $application->getComponent( $component_name )->contactGetFormNames() as $form_name ) {
					if ( ! $form = $application->getComponent( $component_name )->contactGetForm( $form_name ) ) {
						continue;
					}

					$forms[ $form_name ] = $component_name;
				}
			}
			$application->getPlatform()->setCache( $forms, 'contact_forms' );
		}

		return $forms;
	}

	/**
	 * @param Application $application
	 * @param string      $formName
	 * @param bool        $returnFalse
	 * @return IForm
	 */
	public function impl( Application $application, $formName, $returnFalse = false ) {
		if ( ! isset( $this->_impls[ $formName ] ) ) {
			if ( ( ! $forms = $application->Contact_Forms() )
				|| ! isset( $forms[ $formName ] )
				|| ! $application->isComponentLoaded( $forms[ $formName ] )
			) {
				if ( $returnFalse ) {
					return false;
				}
				throw new Exception\UnexpectedValueException( sprintf( 'Invalid contact form: %s', $formName ) );
			}
			$this->_impls[ $formName ] = $application->getComponent( $forms[ $formName ] )->contactGetForm( $formName );
		}

		return $this->_impls[ $formName ];
	}

	public function init( Application $application ) {
		if ( $forms = $this->help( $application ) ) {
			foreach ( array_keys( $forms ) as $form_name ) {
				if ( ( $form = $this->impl( $application, $form_name ) )
					&& $form->contactFormIsEnabled()
				) {
					$form->contactFormInit();
				}
			}
		}
	}

	public function options( Application $application ) {
		$options = array();
		if ( $forms = $this->help( $application ) ) {
			foreach ( array_keys( $forms ) as $form_name ) {
				if ( ( $form = $this->impl( $application, $form_name ) )
					&& $form->contactFormIsEnabled()
					&& ( $list = $form->contactFormList() )
				) {
					$prefix = $form->contactFormInfo( 'title' ) . ' - ';
					foreach ( array_keys( $list ) as $form_id ) {
						$options[ $form_name . '-' . $form_id ] = $prefix . $list[ $form_id ];
					}
				}
			}
		}
		return $options;
	}

	public function renderForm( Application $application, IEntity $entity, $formId ) {
		if ( ! $this->isEnabled( $application, $entity ) ) {
			return;
		}

		if ( ! $pos = strpos( $formId, '-' ) ) {
			return;
		}

		$form_name = substr( $formId, 0, $pos );
		$form_id   = substr( $formId, $pos + 1 );
		$form      = $this->impl( $application, $form_name, true );
		if ( ! $form
			|| ! $form->contactFormIsEnabled()
		) {
			return;
		}

		if ( ! $this->recipients( $application, $entity ) ) {
			if ( $application->getUser()->isAnonymous() ) {
				return;
			}

			if ( ! $application->getUser()->isAdministrator()
				&& $entity->getAuthorId() !== $application->getUser()->id
			) {
				return;
			}

			return sprintf(
				'<div class="%1$salert %1$salert-warning">%2$s</div>',
				DRTS_BS_PREFIX,
				$application->H( __( 'The contact form is hidden because there are no recipients available.', 'directories-pro' ) )
			);
		}

		return $form->contactFormRender( $form_id, $entity );
	}

	public function recipients( Application $application, IEntity $entity ) {
		$recipients = array();
		if ( ( $feature = $application->Entity_Levels_hasFeature( $entity, 'contact_form' ) )
			&& ! empty( $feature['recipients'] )
		) {
			$recipients = $this->_getRecipientsFromSettings( $application, $feature['recipients'], $entity );
		}

		if ( $recipients = $application->Filter( 'contact_email_recipients', $recipients, array( $entity ) ) ) {
			$recipients_normalized = array();
			foreach ( array_keys( $recipients ) as $key ) {
				if ( is_array( $recipients[ $key ] ) ) {
					foreach ( array_keys( $recipients[ $key ] ) as $_key ) {
						$recipients_normalized[] = $recipients[ $key ][ $_key ];
					}
				} else {
					$recipients_normalized[] = $recipients[ $key ];
				}
			}
			$recipients = array_unique( $recipients_normalized );
		}

		return $recipients;
	}

	protected function _getRecipientsFromSettings( Application $application, array $settings, IEntity $entity ) {
		$recipients = array();
		foreach ( $settings as $recipient ) {
			if ( $recipient === 'author' ) {
				if ( ( $author = $application->Entity_Author( $entity ) )
					&& $author->email
				) {
					$recipients[ $recipient ] = $author->email;
				}
			} elseif ( $recipient === 'site' ) {
				if ( $site_email = $application->getPlatform()->getSiteEmail() ) {
					$recipients[ $recipient ] = $site_email;
				}
			} elseif ( ( $field = $application->Entity_Field( $entity, $recipient ) )
					&& ( $field_type = $application->Field_Type( $field->getFieldType(), true ) )
					&& $field_type instanceof IEmail
					&& ( $field_email = $field_type->fieldEmailAddress( $field, $entity, false ) )
				) {

					$recipients[ $recipient ] = $field_email;
			}
		}
		return $recipients;
	}

	public function isEnabled( Application $application, IEntity $entity ) {
		return (bool) $application->Entity_Levels_hasFeature( $entity, 'contact_form' );
	}
}
