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

use SabaiApps\Directories\Component\Entity\Model\Bundle;
use SabaiApps\Directories\Component\Entity\Type\IEntity;
use SabaiApps\Directories\Component\Payment\IPlan;

class FieldsFeature extends AbstractFeature implements IAddonFeature {

	protected function _paymentFeatureInfo() {
		return array(
			'label'            => __( 'Field Settings', 'directories-pro' ),
			'weight'           => 3,
			'default_settings' => array(
				'all'             => true,
				'fields'          => null,
				'fields_disabled' => array(),
			),
		);
	}

	public function paymentFeatureSettingsForm( Bundle $bundle, array $settings, $planType = 'base', array $parents = array() ) {
		if ( ! $options = $this->_getFieldOptions( $bundle ) ) {
			return;
		}

		if ( empty( $settings['fields_disabled'] ) ) {
			$values = array_keys( $options );
		} else {
			$values = $options;
			foreach ( $settings['fields_disabled'] as $field_name ) {
				unset( $values[ $field_name ] );
			}
			$values = array_keys( $values );
		}

		return array(
			'#element_validate' => array(
				array( array( $this, 'submitSettings' ), array( $options ) ),
			),
			'all'               => array(
				'#title'         => __( 'Allowed fields', 'directories-pro' ),
				'#on_label'      => __( 'All fields', 'directories-pro' ),
				'#type'          => 'checkbox',
				'#switch'        => false,
				'#default_value' => ! empty( $settings['all'] ),
				'#horizontal'    => true,
			),
			'fields'            => array(
				'#type'          => 'checkboxes',
				'#options'       => $options,
				'#default_value' => $values,
				'#horizontal'    => true,
				'#columns'       => 2,
				'#states'        => array(
					'invisible' => array(
						sprintf( 'input[name="%s[all][]"]', $this->_application->Form_Form_fieldName( $parents ) ) => array(
							'type'  => 'checked',
							'value' => true,
						),
					),
				),
			),
		);
	}

	protected function _getFieldOptions( Bundle $bundle ) {
		$fields = $options = array();
		foreach ( $this->_application->Entity_Field( $bundle->name ) as $field_name => $field ) {
			if ( ! $field->getFieldWidget()
				|| $field->getFieldData( '_no_ui' )
				|| $field->getFieldData( 'disabled' )
				|| ( ! $field_type = $this->_application->Field_Type( $field->getFieldType(), true ) )
				|| $field_type->fieldTypeInfo( 'admin_only' )
				|| ( ! $field->isCustomField() && ! $field_type->fieldTypeInfo( 'disablable' ) )
			) {
				continue;
			}

			$weight = $field->getFieldData( 'weight' );
			if ( ! isset( $fields[ $weight ] ) ) {
				$fields[ $weight ] = array();
			}
			$fields[ $weight ][ $field_name ] = sprintf( __( '%1$s (%2$s)', 'directories-pro' ), $field, $field_type->fieldTypeInfo( 'label' ) );
		}
		ksort( $fields );
		foreach ( $fields as $_fields ) {
			$options += $_fields;
		}

		return $options;
	}

	public function submitSettings( $form, &$value, $element, $options ) {
		$value['fields_disabled'] = array();
		if ( empty( $value['all'] ) ) {
			foreach ( array_keys( $options ) as $field_name ) {
				if ( ! in_array( $field_name, $value['fields'] ) ) {
					$value['fields_disabled'][] = $field_name;
				}
			}
		}
	}

	public function paymentFeatureOnEntityForm( Bundle $bundle, array $settings, array &$form, ?IEntity $entity = null, $isAdmin = false ) {
		if ( $isAdmin && $this->_application->IsAdministrator() ) {
			return; // do not restrict for administrators
		}

		if ( ! empty( $settings['all'] ) || empty( $settings['fields_disabled'] ) ) {
			return;
		}

		foreach ( array_keys( $form ) as $field_name ) {
			if ( in_array( $field_name, $settings['fields_disabled'] ) ) {
				unset( $form[ $field_name ] );
			}
		}
	}

	public function paymentAddonFeatureSupports( Bundle $bundle ) {
		return true;
	}

	public function paymentAddonFeatureSettingsForm( Bundle $bundle, array $settings, array $parents = array() ) {
		return $this->_getAddonSettingsForm( $bundle, $settings, $parents );
	}

	protected function _getAddonSettingsForm( Bundle $bundle, array $settings, array $parents = array(), $horizontal = true ) {
		if ( ! $options = $this->_getFieldOptions( $bundle ) ) {
			return;
		}

		return array(
			'fields' => array(
				'#title'         => __( 'Additional fields', 'directories-pro' ),
				'#type'          => 'checkboxes',
				'#options'       => $options,
				'#default_value' => isset( $settings['fields'] ) ? $settings['fields'] : null,
				'#horizontal'    => $horizontal,
				'#columns'       => 2,
			),
		);
	}

	public function paymentAddonFeatureExtraSettingsForm( Bundle $bundle, array $planFeatures, array $currentExtraFeatures, array $parents = array() ) {
		$form                     = $this->_getAddonSettingsForm( $bundle, $currentExtraFeatures, $parents, false );
		$form['fields']['#title'] = __( 'Additional fields', 'directories-pro' );
		if ( ! empty( $planFeatures[ $this->_name ]['fields'] ) ) {
			$form['fields']['#options'] = array_diff_key( $form['fields']['#options'], array_flip( $planFeatures[ $this->_name ]['fields'] ) );
		}
		return $form;
	}

	public function paymentAddonFeatureIsEnabled( Bundle $bundle, array $settings ) {
		return ! empty( $settings['fields'] );
	}

	public function paymentAddonFeatureIsOrderable( array $settings, array $currentFeatures ) {
		return empty( $currentFeatures[ $this->_name ]['all'] )
			&& ! empty( $currentFeatures[ $this->_name ]['fields_disabled'] )
			&& ! empty( $settings['fields'] )
			&& array_intersect( $currentFeatures[ $this->_name ]['fields_disabled'], $settings['fields'] );
	}

	public function paymentAddonFeatureExtraIsOrderable( array $planFeatures ) {
		return empty( $planFeatures[ $this->_name ]['all'] )
			&& ! empty( $planFeatures[ $this->_name ]['fields_disabled'] );
		return false;
	}

	public function paymentFeatureApply( IEntity $entity, $featureName, array $featureSettings, array &$values, $orderId, $isAddon = false ) {
		if ( ! $isAddon ) {
			return;
		}

		return $this->_applyAddonFeature( $entity, $featureName, $featureSettings, $values, $orderId );
	}

	public function paymentFeatureUnapply( IEntity $entity, $featureName, array $featureSettings, array &$values, $orderId, $isAddon = false ) {
		if ( ! $isAddon ) {
			return;
		}

		return $this->_unapplyAddonFeature( $entity, $featureName, $featureSettings, $values, $orderId );
	}

	public function paymentFeatureOnEntityFieldValues( IEntity $entity, Bundle $bundle, array $settings ) {
		if ( ! empty( $settings['fields_disabled'] ) ) {
			foreach ( $settings['fields_disabled'] as $field_name ) {
				// TODO: Invoke filter or action to let components modify values
				if ( in_array( $field_name, array( 'post_title', 'post_content' ) ) ) {
					$entity->setFieldValue( $field_name, false );
				} else {
					unset( $entity->$field_name );
				}
			}
		}
	}

	public function paymentFeatureRender( Bundle $bundle, array $settings, ?IPlan $plan = null ) {
		if ( empty( $settings['all'] ) ) {
			if ( ! $count = count( $settings['fields'] ) ) {
				return;
			}

			$label = sprintf( $this->_application->H( _n( '%s field', '%s fields', $count, 'directories-pro' ) ), '<em>' . $count . '</em>' );
		} else {
			$label = $this->_application->H( __( 'All fields', 'directories-pro' ) );
		}
		return array(
			array(
				'icon'     => 'fas fa-list',
				'html'     => $label,
				'settings' => $settings,
			),
		);
	}

	public function paymentAddonFeatureExtraApply( $feature, $extra ) {
		if ( empty( $feature['all'] )
			&& ! empty( $feature['fields_disabled'] )
			&& ! empty( $extra['fields'] )
		) {
			$feature['fields_disabled'] = array_diff( $feature['fields_disabled'], $extra['fields'] );
		}
		return $feature;
	}
}
