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

use SabaiApps\Directories\Application;
use SabaiApps\Directories\Component\Entity\Type\IEntity;
use SabaiApps\Directories\Component\Form\FormComponent;
use SabaiApps\Directories\Component\Payment\IPlan;
use SabaiApps\Directories\Context;
use SabaiApps\Directories\Request;
use SabaiApps\Directories\Exception;
use SabaiApps\Directories\Component\PaymentGateway\PaymentOrder;

abstract class AbstractGateway implements IGateway {

	protected $_application, $_name, $_info;

	public function __construct( Application $application, $name ) {
		$this->_application = $application;
		$this->_name        = $name;
	}

	public function paymentGatewayInfo( $key = null ) {
		if ( ! isset( $this->_info ) ) {
			$this->_info = (array) $this->_paymentGatewayInfo();
		}

		return isset( $key ) ? ( isset( $this->_info[ $key ] ) ? $this->_info[ $key ] : null ) : $this->_info;
	}

	public function paymentGatewayOnCheckoutAction( Context $context, $checkoutAction, $planOrOrder = null, ?IEntity $entity = null, $action = null, array $discountCodes = array() ) {}

	public function paymentGatewayOnOrderRefunded( IEntity $order ) {}

	public function paymentGatewayOrderNotices( IEntity $order ) {
		return array();
	}

	public function paymentGatewayOrderUrl( IEntity $order ) {}

	protected function _getSettings() {
		return (array) $this->_application->getComponent( 'Payment' )
			->getConfig( 'payment', 'components', 'default', 'gateway_settings', $this->_name );
	}

	/**
	 * @param IPlan   $plan
	 * @param IEntity $entity
	 * @param $action
	 * @return IEntity|bool
	 */
	protected function _createOrder( IPlan $plan, IEntity $entity, $action, array $discountCodes = array() ) {
		try {
			$order = $this->_application->PaymentGateway_Order_create( $entity, $plan, $action, $this->_name, $discountCodes );
		} catch ( Exception\IException $e ) {
			$this->_application->logError( 'Failed creating order. Error: ' . $e->getMessage() );
			return false;
		}
		$this->_application->Payment_Util_triggerOrderEvent( 'created', new PaymentOrder( $this->_application, $order ) );

		return $order;
	}

	protected function _completeOrder( IEntity $order, $gatewayOrderId = null, array $data = array(), $throwError = false ) {
		try {
			$this->_application->PaymentGateway_Order_complete( $order, $this->_name, $gatewayOrderId, array( 'data' => $data ) );
		} catch ( Exception\IException $e ) {
			if ( $throwError ) {
				throw $e;
			}
			$this->_application->logError( 'Failed completing order (ID: ' . $order->getId() . '). Error: ' . $e->getMessage() );
			return false;
		}
		return true;
	}

	protected function _deleteOrder( IEntity $order ) {
		try {
			$this->_application->PaymentGateway_Order_delete( $order );
		} catch ( Exception\IException $e ) {
			$this->_application->logError( 'Failed deleting order (ID: ' . $order->getId() . '). Error: ' . $e->getMessage() );
			return false;
		}
		return true;
	}

	protected function _cancelOrder( IEntity $order, array $options = array() ) {
		try {
			$this->_application->PaymentGateway_Order_cancel( $order, $options );
		} catch ( Exception\IException $e ) {
			$this->_application->logError( 'Failed cancelling order (ID: ' . $order->getId() . '). Error: ' . $e->getMessage() );
			return false;
		}
		return true;
	}

	protected function _getCheckoutActionUrl( $checkoutAction, Context $context, $contentType = null, array $params = array() ) {
		$params = array(
			'checkout_action'                 => $checkoutAction,
			'gateway'                         => $this->_name,
			FormComponent::FORM_BUILD_ID_NAME => $context->getRequest()->asStr( FormComponent::FORM_BUILD_ID_NAME ),
		);
		if ( isset( $contentType ) ) {
			$params[ Request::PARAM_CONTENT_TYPE ] = $contentType;
		}
		if ( $parent_entity_id = $context->getRequest()->asInt( 'entity_id' ) ) {
			$params['entity_id'] = $parent_entity_id;
		}
		$params += $params;
		return $this->_application->Url( (string) $context->getRoute(), $params, '', '&' );
	}

	public function paymentGatewayOnWebhook( Context $context ) {}
	public function paymentGatewaySubscriptionUrl( IEntity $subscription ) {}
	public function paymentGatewayCancelSubscription( IEntity $subscription ) {}
	public function paymentGatewayOnLoadAssets() {}

	abstract protected function _paymentGatewayInfo();
}
