<?php
namespace SabaiApps\Directories\Component\PaymentGateway\PaymentComponent;

use SabaiApps\Directories\Component\Payment\Component\AbstractComponent;
use SabaiApps\Directories\Component\Entity\Type\IEntity;
use SabaiApps\Directories\Component\Payment\IOrder;
use SabaiApps\Directories\Component\Payment\IPlan;
use SabaiApps\Directories\Component\Payment\ISubscription;
use SabaiApps\Directories\Component\PaymentGateway\PaymentOrder;
use SabaiApps\Directories\Component\PaymentGateway\PaymentPlan;
use SabaiApps\Directories\Component\PaymentGateway\PaymentSubscription;
use SabaiApps\Directories\Context;
use SabaiApps\Directories\Exception;

class DefaultPaymentComponent extends AbstractComponent {

	protected $_defaultCurrency = 'USD', $_discountCodesFormFieldName = 'discount_codes';

	protected function _paymentComponentInfo() {
		return array(
			'label'            => 'Default',
			'default_settings' => array(
				'gateways'   => null,
				'currency'   => $this->_defaultCurrency,
				'tax_enable' => false,
				'tax'        => array(
					'rate'         => 10,
					'show_include' => false,
				),
			),
		);
	}

	public function paymentIsEnabled() {
		return true;
	}

	public function paymentIsGuestCheckoutEnabled() {
		return true;
	}

	public function paymentIsGuestSignupEnabled() {
		return false;
	}

	public function paymentIsGuestLoginEnabled() {
		return false;
	}

	public function paymentGetCurrency() {
		$settings = $this->getSettings();
		return empty( $settings['currency'] ) ? $this->_defaultCurrency : $settings['currency'];
	}

	public function paymentGetCurrencySymbol() {
		return $this->_application->System_Currency_symbol( $this->paymentGetCurrency() );
	}

	/**
	 * @param string      $bundleName
	 * @param string|null $lang
	 * @return array
	 */
	public function paymentGetPlanIds( $bundleName, $lang = null ) {
		if ( ! $bundle = $this->_application->Entity_Bundle( $bundleName ) ) {
			return array();
		}
		if ( ! $plan_bundle = $this->_application->Entity_Bundle( 'paymentgateway_plan', $bundle->group ) ) {
			return array();
		}

		$plans = $this->_application->Entity_Query( 'post' )
			->fieldIs( 'bundle_name', $plan_bundle->name )
			->fieldIs( 'status', $this->_application->Entity_Status( 'post', 'publish' ) )
			->fieldIs( 'paymentgateway_plan', $bundle->type, 'content_name' )
			->sortByField( 'paymentgateway_plan', 'ASC', 'display_order' )
			->fetch();
		return array_keys( $plans );
	}

	/**
	 * @return IPlan|null
	 */
	public function paymentGetPlanById( $bundleName, $id ) {
		if ( ( ! $bundle = $this->_application->Entity_Bundle( $bundleName ) )
			|| ( ! $plan = $this->_application->Entity_Entity( 'post', $id ) )
			|| $plan->getBundleType() !== 'paymentgateway_plan'
			|| $plan->getSingleFieldValue( 'paymentgateway_plan', 'content_name' ) !== $bundle->type
		) {
			return;
		}

		return new PaymentPlan( $plan );
	}

	/**
	 * @return IOrder|null
	 */
	public function paymentGetOrderById( $id ) {
		if ( ( ! $order = $this->_application->Entity_Entity( 'post', $id ) )
			|| $order->getBundleType() !== 'paymentgateway_order'
		) {
			return;
		}

		return new PaymentOrder( $this->_application, $order );
	}

	/**
	 * @return array
	 */
	public function paymentGetOrders( IEntity $entity, $limit = 0, $offset = 0 ) {
		$ret    = array();
		$orders = $this->_application->Entity_Query( 'post' )
			->fieldIs( 'bundle_type', 'paymentgateway_order' )
			->fieldIs( 'paymentgateway_order', $entity->getType(), 'parent_entity_type' )
			->fieldIs( 'paymentgateway_order', $entity->getId(), 'parent_entity_id' )
			->sortById( 'DESC' )
			->fetch( $limit, $offset );
		foreach ( $orders as $order ) {
			$ret[] = new PaymentOrder( $this->_application, $order );
		}
		return $ret;
	}

	/**
	 * @return array
	 */
	public function paymentGetUserOrders( $userId, $limit = 0, $offset = 0 ) {
		$ret    = array();
		$orders = $this->_application->Entity_Query( 'post' )
			->fieldIs( 'bundle_type', 'paymentgateway_order' )
			->fieldIs( 'author', $userId )
			->sortById( 'DESC' )
			->fetch( $limit, $offset );
		foreach ( $orders as $order ) {
			$ret[] = new PaymentOrder( $this->_application, $order );
		}
		return $ret;
	}

	/**
	 * @return int
	 */
	public function paymentCountUserOrders( $userId ) {
		return $this->_application->Entity_Query( 'post' )
			->fieldIs( 'bundle_type', 'paymentgateway_order' )
			->fieldIs( 'author', $userId )
			->count();
	}

	/**
	 * @return bool
	 */
	public function paymentHasPendingOrder( IEntity $entity, array $actions ) {
		if ( $this->_application->getPlatform()->isTranslatable( $entity->getType(), $entity->getBundleName() ) ) {
			// Include orders for translated entities
			$entity_ids = $this->_application->Entity_Translations_ids( $entity );
		} else {
			$entity_ids = array();
		}
		$entity_ids[] = $entity->getId();
		return $this->_application->Entity_Query( 'post' )
			->fieldIs( 'bundle_type', 'paymentgateway_order' )
			->fieldIs( 'paymentgateway_order', $entity->getType(), 'parent_entity_type' )
			->fieldIsIn( 'paymentgateway_order', $entity_ids, 'parent_entity_id' )
			->fieldIs( 'paymentgateway_order', 'pending_payment', 'status' )
			->fieldIsIn( 'paymentgateway_order', $actions, 'action' )
			->count() > 0;
	}

	public function paymentCheckoutForm( Context $context, $planOrOrder, ?IEntity $entity = null, $action = null ) {
		if ( $planOrOrder instanceof IOrder ) {
			$plan    = $planOrOrder->paymentOrderPlan();
			$user_id = $planOrOrder->paymentOrderUserId();
		} elseif ( $planOrOrder instanceof IPlan ) {
			$plan    = $planOrOrder;
			$user_id = $entity->getAuthorId();
		} else {
			return false;
		}
		if ( ! $this->_application->Payment_Plan_isCheckoutRequired( $plan, $user_id ) ) {
			$order = $planOrOrder instanceof IOrder ? $planOrOrder->getOrder() : $this->_application->PaymentGateway_Order_create( $entity, $plan, $action, '' );
			$this->_application->PaymentGateway_Order_complete( $order );

			return array();
		}

		if ( $checkout_action = $context->getRequest()->asStr( 'checkout_action' ) ) {
			$discount_codes = $context->getRequest()->asArray( $this->_discountCodesFormFieldName, array() );
			if ( ( ! $gateway_name = $context->getRequest()->asStr( 'gateway', 'stripe' ) )
				|| ( ! $gateway = $this->_application->PaymentGateway_Util_gateway( $gateway_name, true ) )
				|| ! $gateway->paymentGatewayOnCheckoutAction( $context, $checkout_action, $planOrOrder, $entity, $action, $discount_codes )
			) {
				return false;
			}

			return isset( $context->paymentgateway_checkout_order_id ) ? array() : null; // return null to prevent complete() form method from being executed
		}

		$form = array(
			'order'   => array(
				'#tree'        => true,
				'#title'       => __( 'Order summary', 'directories-pro' ),
				'#description' => __( 'Please review your order below.', 'directories-pro' ),
				'summary'      => array(
					'#type'   => 'item',
					'#markup' => $this->_application->PaymentGateway_Order_renderSummary( $planOrOrder instanceof IOrder ? $planOrOrder->getOrder() : $plan, $entity, $action ),
				),
			),
			'payment' => array(
				'#tree'        => true,
				'#title'       => __( 'Payment information', 'directories-pro' ),
				'#description' => __( 'Choose a way to pay for your order.', 'directories-pro' ),
				'gateways'     => array(
					'#type'    => 'radios',
					'#group'   => true,
					'#options' => array(),
				),
			),
		);
		if ( $planOrOrder instanceof IPlan
			&& ! $this->_isPercentageDiscountApplied( $planOrOrder )
		) {
			$this->_application->getPlatform()->addJsFile( 'paymentgateway-checkout-form.min.js', 'drts-paymentgateway-checkout-form', 'drts', 'directories-pro' );
			$form['order']['discount_code_apply'] = array(
				'#type'                   => 'textfield',
				'#title'                  => __( 'Discount code', 'directories-pro' ),
				'#size'                   => 20,
				'#maxlength'              => 50,
				'#attributes'             => array( 'style' => 'text-transform:uppercase;' ),
				'#description'            => __( 'If you have a discount code, please enter it here.', 'directories-pro' ),
				'#class'                  => 'drts-paymentgateway-discount-code-apply',
				'#field_suffix'           => $this->_application->H( __( 'Apply', 'directories-pro' ) ),
				'#field_suffix_btn'       => true,
				'#field_suffix_btn_class' => 'secondary',
				'#js_ready'               => 'DRTS.PaymentGateway.initDiscountCodeHandlers("#__FORM_ID__", {
                    verifyUrl: "' . $this->_application->Url( '/_drts/paymentgateway/verify_discount_code', array(), '', '&' ) . '",
                    planId: "' . $this->_application->H( $plan->paymentPlanId() ) . '",
                    token: "' . $this->_application->H( $this->_application->Form_Form_createToken( 'paymentgateway_verify_discount_code', 1800, true ) ) . '",
                    codeFormFieldName: "' . $this->_application->H( $this->_discountCodesFormFieldName ) . '",
                    labelDiscount: "' . $this->_application->H( __( 'Discount', 'directories-pro' ) ) . '",
                    labelAlreadyApplied: "' . $this->_application->H( __( 'This discount code has already been applied.', 'directories-pro' ) ) . '",
                    container: "' . $this->_application->H( $context->getContainer() ) . '"
                })',
			);
		}
		$settings = $this->getSettings();
		if ( ! empty( $settings['gateways']['default'] ) ) {
			$plan_type = $plan->paymentPlanType();
			foreach ( $settings['gateways']['default'] as $gateway_name ) {
				if ( ( ! $gateway = $this->_application->PaymentGateway_Util_gateway( $gateway_name, true ) )
					|| ! in_array( $plan_type, (array) $gateway->paymentGatewayInfo( 'plan_types' ) )
				) {
					continue;
				}

				$form['payment']['gateways']['#options'][ $gateway_name ] = $settings['gateways']['options'][ $gateway_name ];
				$gateway_checkout_form                                    = $gateway->paymentGatewayCheckoutForm( $context, $plan, $entity, $action, array( 'payment', 'gateways', $gateway_name ), $this->_discountCodesFormFieldName );
				if ( $gateway_checkout_form ) {
					$form['payment']['gateway_settings'][ $gateway_name ] = array(
						'#states' => array(
							'visible' => array(
								'[name="payment[gateways]"]' => array(
									'type'  => 'one',
									'value' => $gateway_name,
								),
							),
						),
					) + $gateway_checkout_form;
				}
			}
		}
		if ( empty( $form['payment']['gateways']['#options'] ) ) {
			$form['payment']['gateways']['#type']   = 'markup';
			$form['payment']['gateways']['#markup'] = '<div class="' . DRTS_BS_PREFIX . 'alert ' . DRTS_BS_PREFIX . 'alert-danger">' . __( 'There are no payment methods available.', 'directories-pro' ) . '</div>';
		} elseif ( count( $form['payment']['gateways']['#options'] ) === 1 ) {
				$form['payment']['gateways']['#type']          = 'hidden';
				$form['payment']['gateways']['#default_value'] = array_keys( $form['payment']['gateways']['#options'] )[0];
				$form['payment']['#title']                     = $form['payment']['#description'] = '';
		}

		return $form;
	}

	protected function _isPercentageDiscountApplied( IPlan $plan ) {
		if ( ( $plan_entity = $plan->getPlan() )
			&& ( $discount = $plan_entity->getSingleFieldValue( 'paymentgateway_plan_discount' ) )
		) { // A discount is applied to the plan
			$this->_application->Entity_Field_load( $discount );
			if ( $discount->getSingleFieldValue( 'paymentgateway_discount', 'discount_type' ) === 'percentage' ) {
				return true;
			}
		}
		return false;
	}

	public function paymentCheckoutComplete( Context $context, IPlan $plan, IEntity $entity, $action ) {
		if ( ! isset( $context->paymentgateway_checkout_order_id ) ) {
			return;
		}

		$context->setView();
		if ( ! empty( $context->paymentgateway_checkout_order_id ) ) {
			$title = __( 'Thank you for your order!', 'directories-pro' );
			if ( $order = $this->_application->Entity_Entity( 'post', $context->paymentgateway_checkout_order_id ) ) {
				$content = $this->_getOrderDetailHtml( $order, false );
			} else {
				$this->_application->logError( $content = 'Failed fetching order after payment completed (Order ID: ' . $context->paymentgateway_checkout_order_id . ').' );
			}
		} else {
			$title = __( 'Your order was cancelled.', 'directories-pro' );
			if ( $action !== 'claim' ) {
				if ( $flash = $context->getFlash() ) {
					$alerts = array();
					foreach ( $flash as $_flash ) {
						if ( ! strlen( $_flash['msg'] ) ) {
							continue;
						}

						$alerts[] = '<div class="' . DRTS_BS_PREFIX . 'alert ' . DRTS_BS_PREFIX . 'alert-' . $_flash['level'] . '">' . $this->_application->H( $_flash['msg'] ) . '</div>';
					}
					if ( ! empty( $alerts ) ) {
						$content = implode( PHP_EOL, $alerts );
					}
				}
			} else {
				try {
					$this->_application->Entity_Types_impl( $entity->getType() )->entityTypeDeleteEntities( array( $entity ) );
				} catch ( Exception\IException $e ) {
					$this->_application->logError( 'Failed deleting cancelled claim (ID: ' . $entity->getId() . '). Error: ' . $e->getMessage() );
				}
			}
		}
		$context->clearFlash()->setTitle( $title )->setAttributes( array( 'content' => isset( $content ) ? $content : $title ) );
	}

	protected function _getOrderDetailHtml( IEntity $order, $showActions = true ) {
		$notices = $actions = array();
		if ( ( $gateway_name = $order->getSingleFieldValue( 'paymentgateway_order', 'gateway' ) )
			&& ( $gateway = $this->_application->PaymentGateway_Util_gateway( $gateway_name ) )
		) {
			$notices = (array) $gateway->paymentGatewayOrderNotices( $order );
		}
		if ( $showActions ) {
			if ( $order->getSingleFieldValue( 'paymentgateway_order', 'status' ) === 'pending_payment' ) {
				$actions['pay']          = $this->_application->LinkTo(
					__( 'Pay now', 'directories-pro' ),
					$this->_application->Dashboard_Panels_panelUrl( 'payment_payments', 'orders', '/payment_orders/' . $order->getId() . '/pay', array(), true ),
					array( 'btn' => true ),
					array( 'class' => DRTS_BS_PREFIX . 'btn ' . DRTS_BS_PREFIX . 'btn-primary' )
				);
				$actions['cancel_order'] = $this->_application->LinkTo(
					$cancel_label        = __( 'Cancel order', 'directories-pro' ),
					$this->_application->Dashboard_Panels_panelUrl( 'payment_payments', 'orders', '/payment_orders/' . $order->getId() . '/cancel_order', array(), true ),
					array(
						'btn'       => true,
						'container' => 'modal',
					),
					array(
						'class'            => DRTS_BS_PREFIX . 'btn ' . DRTS_BS_PREFIX . 'btn-outline-secondary',
						'data-modal-title' => $order->getSingleFieldValue( 'paymentgateway_order', 'number' ) . ' - ' . $cancel_label,
					)
				);
			}
		}
		return $this->_application->Render(
			array( 'paymentgateway_order_details', 'directories-pro' ),
			array(
				'order'   => $order,
				'notices' => $notices,
				'actions' => $actions,
			)
		);
	}

	/**
	 * @return bool
	 */
	public function paymentIsSubscriptionEnabled() {
		return true;
	}

	/**
	 * @return ISubscription|null
	 */
	public function paymentGetSubscriptionById( $id ) {
		if ( ( ! $subscription = $this->_application->Entity_Entity( 'post', $id ) )
			|| $subscription->getBundleType() !== 'paymentgateway_subscription'
		) {
			return;
		}

		return new PaymentSubscription( $this->_application, $subscription );
	}

	public function paymentGetSubscriptions( IEntity $entity, $limit = 0, $offset = 0 ) {
		$ret           = array();
		$subscriptions = $this->_application->Entity_Query( 'post' )
			->fieldIs( 'bundle_type', 'paymentgateway_subscription' )
			->fieldIs( 'paymentgateway_subscription', $entity->getType(), 'parent_entity_type' )
			->fieldIs( 'paymentgateway_subscription', $entity->getId(), 'parent_entity_id' )
			->sortById( 'DESC' )
			->fetch( $limit, $offset );
		foreach ( $subscriptions as $subscription ) {
			$ret[] = new PaymentSubscription( $this->_application, $subscription );
		}
		return $ret;
	}

	/**
	 * @return array
	 */
	public function paymentGetUserSubscriptions( $userId, $limit = 0, $offset = 0 ) {
		$ret           = array();
		$subscriptions = $this->_application->Entity_Query( 'post' )
			->fieldIs( 'bundle_type', 'paymentgateway_subscription' )
			->fieldIs( 'author', $userId )
			->sortById( 'DESC' )
			->fetch( $limit, $offset );
		foreach ( $subscriptions as $subscription ) {
			$ret[] = new PaymentSubscription( $this->_application, $subscription );
		}
		return $ret;
	}

	/**
	 * @return int
	 */
	public function paymentCountUserSubscriptions( $userId ) {
		return $this->_application->Entity_Query( 'post' )
			->fieldIs( 'bundle_type', 'paymentgateway_subscription' )
			->fieldIs( 'author', $userId )
			->count();
	}

	/**
	 * @return int
	 */
	public function paymentGetClaimOrderId( IEntity $claim, IEntity $claimedEntity ) {
		$orders = $this->_application->Entity_Query( 'post' )
			->fieldIs( 'bundle_type', 'paymentgateway_order' )
			->fieldIs( 'paymentgateway_order', $claimedEntity->getType(), 'parent_entity_type' )
			->fieldIs( 'paymentgateway_order', $claimedEntity->getId(), 'parent_entity_id' )
			->fieldIs( 'paymentgateway_order', 'claim', 'action' )
			->fetch( 1, 0, null, false );
		if ( ( empty( $orders )
			|| ( ! $order = array_shift( $orders ) ) )
		) {
			return 0;
		}

		return $order->getId();
	}

	/**
	 * @param $orderId
	 * @param string $reason
	 */
	public function paymentRefundOrder( $orderId, $reason = '' ) {
		if ( ! $order = $this->_application->Entity_Entity( 'post', $orderId ) ) {
			return;
		}

		$this->_application->PaymentGateway_Order_refund( $order, $reason );
	}

	/**
	 * @return int
	 * @param $planId
	 * @param $lang string
	 */
	public function paymentGetPlanId( $bundleName, $planId, $lang ) {
		return $planId;
	}

	public function paymentFormatPlanPrice( IPlan $plan ) {
		$price    = $plan->paymentPlanPrice();
		$settings = $this->getSettings();
		$tax_rate = null;
		if ( ! empty( $settings['tax_enable'] )
			&& ! empty( $settings['tax']['rate'] )
			&& ! empty( $settings['tax']['show_include'] )
		) {
			$tax_rate = $settings['tax']['rate'];
			$price   *= ( 1 + $tax_rate / 100 );
		}
		$currency        = empty( $settings['currency'] ) ? $this->_defaultCurrency : $settings['currency'];
		$price_formatted = $this->_application->System_Currency_format( $price, $currency );
		if ( $discount = $this->_application->PaymentGateway_Util_hasDiscount( $plan ) ) {
			if ( $discount->getSingleFieldValue( 'paymentgateway_discount', 'discount_type' ) === 'percentage' ) {
				$sale_price = $plan->paymentPlanPrice() * ( 1 - $discount->getSingleFieldValue( 'paymentgateway_discount', 'discount_value' ) / 100 );
			} else {
				$sale_price = $plan->paymentPlanPrice() - $discount->getSingleFieldValue( 'paymentgateway_discount', 'discount_value' );
			}
			$sale_price *= ( 1 + $tax_rate / 100 );
			$ret         = '<span class="drts-payment-plan-discount-price ' . DRTS_BS_PREFIX . 'text-primary" title="'
				. $this->_application->H( $discount->getTitle() ) . '" rel="sabaitooltip">'
				. $this->_application->System_Currency_format( $sale_price, $currency )
				. '</span> <del class="drts-payment-plan-original-price">'
				. $price_formatted . '</del>';
		} else {
			$ret = '<span class="drts-payment-plan-original-price">'
				. $price_formatted . '</span>';
		}
		if ( $plan->paymentPlanType() === 'subscription' ) {
			$ret .= $this->_getSubscriptionPriceSuffix( $plan->paymentPlanInterval(), $plan->paymentPlanIntervalCount() );
		}
		return '<span class="drts-payment-plan-price">' . $ret . '</span>';
	}

	protected function _getSubscriptionPriceSuffix( $interval, $intervalCount ) {
		switch ( $interval ) {
			case 'year':
				$interval_label = sprintf( _n( 'year', '%d years', $intervalCount, 'directories-pro' ), $intervalCount );
				break;
			case 'month':
				$interval_label = sprintf( _n( 'month', '%d months', $intervalCount, 'directories-pro' ), $intervalCount );
				break;
			case 'week':
				$interval_label = sprintf( _n( 'week', '%s weeks', $intervalCount, 'directories-pro' ), $intervalCount );
				break;
			case 'day':
				$interval_label = sprintf( _n( 'day', '%s days', $intervalCount, 'directories-pro' ), $intervalCount );
				break;
			default:
				return '';
		}
		return '<span class="drts-payment-plan-price-interval">/'
			. '<span class="drts-payment-plan-price-interval-label">'
			. $this->_application->H( $interval_label ) . '</span></span>';
	}

	/**
	 * @param array $settings
	 * @param array $parents
	 * @return array
	 */
	public function paymentSettingsForm( array $settings, array $parents ) {
		// Fetch all available payment gateways
		$gateways = $gateway_settings_form = array();
		foreach ( array_keys( $this->_application->PaymentGateway_Util_gateways() ) as $gateway_name ) {
			if ( ! $gateway = $this->_application->PaymentGateway_Util_gateway( $gateway_name, true ) ) {
				continue;
			}

			$gateways[ $gateway_name ] = $gateway->paymentGatewayInfo( 'label' );
			$_settings                 = isset( $settings['gateway_settings'][ $gateway_name ] ) ? $settings['gateway_settings'][ $gateway_name ] : array();
			$_settings                += (array) $gateway->paymentGatewayInfo( 'default_settings' );
			if ( $settings_form = $gateway->paymentGatewaySettingsForm( $_settings, array_merge( $parents, array( 'gateway_settings', $gateway_name ) ) ) ) {
				foreach ( array_keys( $settings_form ) as $setting_key ) {
					if ( isset( $settings_form[ $setting_key ]['#required'] )
						&& $settings_form[ $setting_key ]['#required'] === true
					) {
						$settings_form[ $setting_key ]['#required'] = function ( $form ) use ( $gateway_name, $parents ) {
							return in_array( $gateway_name, (array) $form->getValue( array_merge( $parents, array( 'gateways', 'default' ) ) ) );
						};
					}
				}
				$gateway_settings_form[ $gateway_name ] = array(
					'#title'               => sprintf( __( 'Payment Method Settings (%s)', 'directories-pro' ), $gateways[ $gateway_name ] ),
					'#horizontal_children' => true,
					'#class'               => 'drts-form-label-lg',
					'#states'              => array(
						'visible' => array(
							sprintf( '[name="%s[gateways][default][]"][data-option-value="' . $gateway_name . '"]', $this->_application->Form_Form_fieldName( $parents ) ) => array(
								'type'  => 'empty',
								'value' => false,
							),
						),
					),
				) + $settings_form;
			}
		}
		$form = array(
			'gateways'   => array(
				'#title'                  => __( 'Payment methods', 'directories-pro' ),
				'#weight'                 => 1,
				'#type'                   => 'options',
				'#disable_add'            => true,
				'#disable_icon'           => true,
				'#disable_add_csv'        => true,
				'#multiple'               => true,
				'#options_value_disabled' => true,
				'#default_value'          => array(
					'options' => isset( $settings['gateways']['options'] ) ? $settings['gateways']['options'] : $gateways,
					'default' => isset( $settings['gateways']['default'] ) ? $settings['gateways']['default'] : null,
				),
				'#horizontal'             => true,
			),
			'currency'   => array(
				'#weight'        => 10,
				'#title'         => __( 'Currency', 'directories-pro' ),
				'#type'          => 'select',
				'#options'       => $this->_application->System_Currency_options(),
				'#default_value' => isset( $settings['currency'] ) ? $settings['currency'] : 'USD',
				'#horizontal'    => true,
			),
			'tax_enable' => array(
				'#weight'        => 11,
				'#title'         => __( 'Enable tax', 'directories-pro' ),
				'#type'          => 'checkbox',
				'#default_value' => ! empty( $settings['tax_enable'] ),
				'#horizontal'    => true,
			),
			'tax'        => array(
				'#weight'      => 12,
				'#states'      => array(
					'visible' => array(
						sprintf( '[name="%s"]', $this->_application->Form_Form_fieldName( array_merge( $parents, array( 'tax_enable' ) ) ) ) => array(
							'type'  => 'checked',
							'value' => true,
						),
					),
				),
				'rate'         => array(
					'#title'         => __( 'Tax rate', 'directories-pro' ),
					'#type'          => 'number',
					'#step'          => 0.01,
					'#default_value' => isset( $settings['tax']['rate'] ) ? $settings['tax']['rate'] : null,
					'#horizontal'    => true,
					'#field_suffix'  => '%',
				),
				'show_include' => array(
					'#title'         => __( 'Show prices with tax included', 'directories-pro' ),
					'#type'          => 'checkbox',
					'#default_value' => ! empty( $settings['tax']['show_include'] ),
					'#horizontal'    => true,
				),
			),

		);
		if ( ! empty( $gateway_settings_form ) ) {
			$form['gateway_settings']            = $gateway_settings_form;
			$form['gateway_settings']['#weight'] = 20;
		}

		return $form;
	}

	public function paymentGetOrderDetailHtml( IOrder $order ) {
		return $this->_getOrderDetailHtml( $order->getOrder() );
	}

	public function paymentGetSubscriptionDetailHtml( ISubscription $subscription ) {
		$actions = array();
		if ( $subscription->paymentSubscriptionIsActive() ) {
			$actions['cancel_subscription'] = $this->_application->LinkTo(
				$cancel_label               = __( 'Cancel subscription', 'directories-pro' ),
				$this->_application->Dashboard_Panels_panelUrl( 'payment_payments', 'orders', '/payment_subscriptions/default-' . $subscription->paymentSubscriptionId() . '/cancel_subscription', array(), true ),
				array(
					'btn'       => true,
					'container' => 'modal',
				),
				array(
					'class'            => DRTS_BS_PREFIX . 'btn ' . DRTS_BS_PREFIX . 'btn-outline-secondary',
					'data-modal-title' => $subscription->paymentSubscriptionNumber() . ' - ' . $cancel_label,
				)
			);
		}
		return $this->_application->Render(
			array( 'paymentgateway_subscription_details', 'directories-pro' ),
			array(
				'subscription' => $subscription->getSubscription(),
				'notices'      => array(),
				'actions'      => $actions,
			)
		);
	}

	public function paymentIsOrderCancellable() {
		return true;
	}

	public function paymentCancelOrder( IOrder $order, $isManual = false ) {
		$this->_application->PaymentGateway_Order_cancel( $order->getOrder() );
	}

	public function paymentIsSubscriptionCancellable() {
		return true;
	}

	public function paymentCancelSubscription( ISubscription $subscription, $isManual = false ) {
		$this->_application->PaymentGateway_Subscription_cancel( $subscription->getSubscription(), $isManual );
	}

	public function paymentGetPlanContentBundleName( IPlan $plan ) {
		if ( ( ! $plan_entity = $plan->getPlan() )
			|| ( ! $content_bundle_type = $plan_entity->getSingleFieldValue( 'paymentgateway_plan', 'content_name' ) )
			|| ( ! $plan_bundle = $this->_application->Entity_Bundle( $plan_entity->getBundleName() ) )
			|| ( ! $content_bundle = $this->_application->Entity_Bundle( $content_bundle_type, $plan_bundle->group ) )
		) {
			return '';
		}

		return $content_bundle->name;
	}

	public function paymentPlanHasDiscount( IPlan $plan ) {
		return $this->_application->PaymentGateway_Util_hasDiscount( $plan ) ? true : false;
	}
}
