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

use SabaiApps\Directories\Context;
use SabaiApps\Directories\Component\Form\Form;
use SabaiApps\Directories\Component\Entity\Type\IEntity;
use SabaiApps\Directories\Component\Entity\Model\Bundle;

abstract class AbstractAddEntity extends AbstractSubmitEntity {

	protected function _getSteps( Context $context, array &$formStorage ) {
		// Save reference field name and ID to storage for later use if requested
		if ( ( $entity_reference_field = $context->getRequest()->asStr( 'entity_reference_field' ) )
			&& ( $entity_reference_id = $context->getRequest()->asStr( 'entity_reference_id' ) )
		) {
			$formStorage['entity_reference_field'] = $entity_reference_field;
			$formStorage['entity_reference_id']    = $entity_reference_id;
		}

		return array(
			'add' => array( 'order' => 10 ),
		);
	}

	protected function _getPageTitle( Context $context, Bundle $bundle, array $formStorage ) {}

	protected function _assignPageTitle( Context $context, Bundle $bundle, array $formStorage ) {
		$title = $this->Filter( 'frontendsubmit_add_entity_page_title', $this->_getPageTitle( $context, $bundle, $formStorage ), array( $bundle ) );
		$context->setTitle( is_string( $title ) && strlen( $title ) ? $title : null );
	}

	public function _getFormForStepAdd( Context $context, array &$formStorage ) {
		$bundle = $this->_getBundle( $context, $formStorage );

		// Check if submission is restricted
		if ( ! $this->_isSubmitAllowed( $context, $formStorage, $bundle ) ) {
			return false;
		}

		$this->_assignPageTitle( $context, $bundle, $formStorage );

		if ( ! $entity_or_bundle = $this->_getEntity( $context, $formStorage ) ) {
			$entity_or_bundle = $bundle;
		}
		$form = $this->_getSubmitEntityForm(
			$context,
			$formStorage,
			$entity_or_bundle,
			$this->_getSubmitButtonForStepAdd( $context, $formStorage )
		);

		// Remove reference type field that will be populated automatically during save
		if ( ! empty( $formStorage['entity_reference_field'] )
			&& isset( $form['drts'][ $formStorage['entity_reference_field'] ] )
		) {
			unset( $form['drts'][ $formStorage['entity_reference_field'] ] );
		}

		if ( $this->getUser()->isAnonymous() ) {
			if ( ! isset( $formStorage['_guest'] ) ) {
				// Guest redirection to login/registration form was suppressed, so add link allow login/registration
				$login_url         = $this->getPlatform()->getLoginUrl( $this->_getRedirectGuestUrl( $context, $form, $bundle ) );
				$form['#header'][] = array(
					'level'     => 'info',
					'message'   => $this->H( __( 'Already registered?', 'directories-pro' ) )
						. ' <a href="' . $login_url . '">' . $this->H( __( 'Login or Sign Up', 'directories-pro' ) ) . '</a>',
					'no_escape' => true,
				);
			}
		}

		return $form;
	}

	public function _submitFormForStepAdd( Context $context, Form $form ) {
		$bundle = $this->_getBundle( $context, $form->storage );

		$values = $this->_getEntityValues( $context, $form, $bundle );

		// Set referencing entity if any
		if ( ! empty( $form->storage['entity_reference_field'] )
			&& $this->Entity_Field( $bundle, $form->storage['entity_reference_field'] ) // Make sure field belongs to current bundle
		) {
			$values[ $form->storage['entity_reference_field'] ] = $form->storage['entity_reference_id'];
		}

		// Set max num items if any
		$extra_args                               = array();
		$extra_args['entity_field_max_num_items'] = $form->settings['#entity_field_max_num_items'];

		// Save
		if ( ! $entity = $this->_getEntity( $context, $form->storage ) ) {
			$bundle = $this->_getBundle( $context, $form->storage );
			// Create entity and save entity id into session for later use
			$entity                     = $this->Entity_Save( $bundle->name, array( 'status' => $this->_getEntityStatus( $context, $form, $bundle ) ) + $values, $extra_args );
			$form->storage['entity_id'] = $entity->getId();
		} else {
			$entity = $this->Entity_Save( $entity, $values, $extra_args );
		}
		$form->settings['#entity'] = $entity;
	}

	protected function _getSubmitButtonForStepAdd( Context $context, array &$formStorage ) {}

	protected function _getEntityStatus( Context $context, Form $form, Bundle $bundle ) {
		if ( ! empty( $bundle->info['public'] )
			&& ! $this->HasPermission( 'entity_publish_' . $bundle->name )
		) {
			$status = 'pending';
		} else {
			$status = 'publish';
		}
		return $this->Entity_Status( $bundle->entitytype_name, $status );
	}

	protected function _getEntityValues( Context $context, Form $form, Bundle $bundle ) {
		$values = $form->values['drts'];
		if ( $this->getUser()->isAnonymous() ) {
			if ( ! empty( $form->storage['_guest'] ) ) {
				$guest_info                     = $form->storage['_guest'];
				$values['frontendsubmit_guest'] = array(
					'name'  => isset( $guest_info['name'] ) ? $guest_info['name'] : '',
					'email' => isset( $guest_info['email'] ) ? $guest_info['email'] : '',
					'url'   => isset( $guest_info['url'] ) ? $guest_info['url'] : '',
				);
			} else {
				$values['frontendsubmit_guest'] = array(
					'ip' => null,
				);
			}
		}
		return $values;
	}

	protected function _complete( Context $context, array $formStorage ) {
		$entity = $this->_getEntity( $context, $formStorage );

		// Set cookie to track guest user
		if ( $entity
			&& $this->getUser()->isAnonymous()
		) {
			if ( $email = $entity->getSingleFieldValue( 'frontendsubmit_guest', 'email' ) ) {
				$this->Dashboard_GuestAccess_grant( $email );
			}
			// $this->FrontendSubmit_GuestAuthor_setCookie($entity);
		}

		// Set success redirection URL
		$success_url          = $this->Filter(
			'frontendsubmit_add_entity_success_url',
			$orig_success_url = $this->_getSuccessUrl( $context, $formStorage, $entity ),
			array( $entity )
		);
		$context->setSuccess( $success_url );

		// Only add flash when redirecting to original success URL
		if ( $orig_success_url === $success_url
			|| strpos( $success_url, $orig_success_url ) === 0
		) {
			if ( $entity
				&& $entity->isDraft()
			) {
				$success_msg = $this->Filter(
					'frontendsubmit_add_entity_draft_success_msg',
					$this->H( __( 'Your item has been saved as draft. You can re-submit your item from the dashboard page.', 'directories-pro' ) ),
					array( $entity )
				);
				$context->addFlash( $success_msg, 'success', 60000 );
			} else {
				$success_msg = $this->Filter(
					'frontendsubmit_add_entity_success_msg',
					$this->H( __( 'Your item has been submitted successfully.', 'directories-pro' ) ),
					array( $entity )
				);
				$context->addFlash( $success_msg, 'success', 60000 );

				// Add extra flash if entity is pending review
				if ( $entity
					&& $entity->isPending()
				) {
					$info_msg = $this->Filter(
						'frontendsubmit_add_entity_success_msg2',
						$this->H( __( 'We will review your submission and publish it on this site when it is approved.', 'directories-pro' ) ),
						array( $entity )
					);
					$context->addFlash( $info_msg, 'info', 60000 );
				}
			}
		}
	}

	protected function _getSuccessUrl( $context, $formStorage, ?IEntity $entity = null ) {
		if ( ! isset( $entity ) ) {
			return $this->getPlatform()->getSiteUrl();
		}

		// Redirect to URL of referenced entity if any
		if ( ! empty( $formStorage['entity_reference_id'] )
			&& ( $referenced_entity = $this->Entity_Entity( $entity->getType(), $formStorage['entity_reference_id'] ) )
		) {
			return $this->Entity_PermalinkUrl( $referenced_entity );
		}

		if ( ! $bundle = $this->Entity_Bundle( $entity ) ) {
			return $this->getPlatform()->getSiteUrl(); // failed fetching bundle, redirect to site URL
		}

		// If not published, redirect to URL of parent entity if any or to dashboard page if logged in, otherwise to main index page
		if ( ! $entity->isPublished()
			|| empty( $bundle->info['public'] )
		) {
			if ( ! empty( $bundle->info['parent'] ) ) {
				if ( $parent_entity = $this->_getParentEntity( $context, $formStorage ) ) {
					return $this->Entity_PermalinkUrl( $parent_entity ); // redirect to parent entity
				}
			}

			if ( $this->getUser()->isAnonymous() ) {
				return $this->Url( $bundle->getPath() ); // redirect to main index
			}
			return $this->Url( '/' . $this->getComponent( 'Dashboard' )->getSlug( 'dashboard' ) ); // redirect to dashboard
		}
		return $this->Entity_PermalinkUrl( $entity );
	}

	protected function _getEntity( Context $context, array $formStorage ) {
		return ( ! empty( $formStorage['entity_id'] )
			&& ( $entity = $this->Entity_Entity( $this->_getBundle( $context, $formStorage )->entitytype_name, $formStorage['entity_id'] ) )
		) ? $entity : null;
	}

	protected function _isGuestRedirectRequired( Context $context, $bundleType, array &$formStorage ) {
		if ( ! $this->Filter( 'frontendsubmit_redirect_guest_check', true, array( $bundleType ) ) ) {
			return false;
		}

		if ( ! isset( $formStorage['_guest'] )
			&& ( $guest_info = $context->getRequest()->get( '_guest' ) )
		) {
			$formStorage['_guest'] = is_array( $guest_info ) ? $guest_info : array();
		}

		if ( isset( $formStorage['_guest'] ) ) {
			return false; // came by clicking "Continue as Guest"
		}

		$ret = $this->getComponent( 'FrontendSubmit' )->hasCustomLoginRegistrationPage();

		if ( ! $this->Filter( 'frontendsubmit_redirect_guest', $ret ) ) {
			return false;
		}

		return true;
	}

	protected function _getRedirectGuestUrlParams( Context $context, array $formStorage ) {
		return array();
	}

	protected function _redirectGuest( Context $context, array $formStorage, $bundle = null ) {
		if ( ! $this->getUser()->isAnonymous() ) {
			return;
		}

		$context->setUnauthorizedError( $this->_getRedirectGuestUrl( $context, $formStorage, $bundle ) );
	}

	protected function _getAddEntityUrl( Context $context, array $params = array() ) {
		return $this->Url( (string) $context->getRoute(), $params, '', '&' );
	}

	protected function _getRedirectGuestUrl( Context $context, array $formStorage, $bundle = null ) {
		$params = array();
		// Add extra params if any
		if ( $param_names = $this->_getRedirectGuestUrlParams( $context, $formStorage ) ) {
			foreach ( $param_names as $param ) {
				if ( isset( $_GET[ $param ] ) ) {
					$params[ $param ] = $_GET[ $param ];
				}
			}
		}
		if ( isset( $bundle ) ) {
			$params['redirect_action'] = 'add';
			if ( $bundle instanceof Bundle ) {
				$params['redirect_bundle'] = $bundle->name;
				if ( ! empty( $bundle->info['parent'] )
					&& ( $parent_entity = $this->_getParentEntity( $context, $formStorage ) )
				) {
					$params['redirect_entity'] = $parent_entity->getId();
				}
			} else {
				$params['redirect_bundle_type'] = $bundle;
			}
			if ( $redirect_param_names = $this->Entity_BundleTypeInfo( $bundle, 'frontendsubmit_guest_redirect_params' ) ) {
				foreach ( $redirect_param_names  as $param ) {
					if ( isset( $_GET[ $param ] ) ) {
						$params[ $param ] = $_GET[ $param ];
					}
				}
			}
		}
		return $this->_getAddEntityUrl( $context, $params );
	}
}
