<?php

namespace Icetech\Payment\Gateway;

use Icetech\Payment\Gateway\Payment\Response;

/**
 * Description of Payment
 *
 * @author Sergiu
 */
abstract class PaymentGateway
{

    const STATUS_PAID = 'paid';
    const STATUS_PREAUTHORIZED = 'preauthorized';
    const STATUS_CANCELED = 'canceled';
    const STATUS_REFUNDED = 'refunded';
    const STATUS_PENDING = 'pending';
    const STATUS_ERROR = 'canceled';


    protected $endpoint_url;
    protected $merchant_id;
    protected $public_key_path;
    protected $private_key_path;
    protected $testMode;
    protected $currency;
    protected $confirm_url;
    protected $cancel_url;
    protected $return_url;
    protected $installment = false;
    protected $amount = null; // amount of da order
    protected $order_id = null; // order id
    protected $order;
    protected $details = []; //customer data.

    /** @var Response * */
    protected $response; // response object.
    protected $status = []; // list of status keys associations
    protected $errros = []; // list of errors

    public function __construct()
    {

    }

    /**
     * Loaded needed config.
     */
    public function initConfig()
    {
        $config = config(config('payment.gateway') . '.' . ($this->testMode ? 'test' : 'live'));
        foreach ($config as $key => $value) {
            $this->$key = $value;
        }
    }

    public function istTestMode()
    {
        return $this->testMode;
    }

    public function setTestMode($testMode = true)
    {

        $this->testMode = $testMode;
        $this->initConfig();
        return $this;
    }

    public function getAmount()
    {
        return $this->amount;
    }

    public function setAmount($value)
    {
        $this->amount = $value;
        return $this;
    }

    public function setOrder($order)
    {
        $this->order = $order;
        return $this;
    }

    public function getCurrency()
    {
        return $this->currency;
    }

    public function setCurrency($value)
    {
        $this->currency = $value;
        return $this;
    }

    public function getOrderId()
    {
        return $this->order_id;
    }

    public function setOrderId($value)
    {
        $this->order_id = $value;
        return $this;
    }

    public function setInstallment($condition = false, $period = null)
    {
        $this->installment = $condition;
        if ($condition && $period) {
            $this->installment_period = $period;
        }
        return $this;
    }

    /**
     *  we map the contact (which is a Eloquent Contact) to what's asked by each provider.
     *
     * @param type $values
     * @return $this
     */
    public function setDetails($values)
    {
        if (!is_array($values)) {

            $details = [];
            foreach ($this->getContactKeyMappings() as $key => $key_source) {
                if (is_array($key_source)) {
                    if ($values->{$key_source[0]}) {
                        $details[$key] = $values->{$key_source[0]}->{$key_source[1]};
                    }
                } else {
                    $details[$key] = $values->$key_source;
                }
            }
            $this->details = $details;
            return $this;
        }

        $this->details = $values;
        return $this;
    }

    public function getUrl()
    {
        return $this->endpoint_url;
    }

    public function getResponseData()
    {
        return $this->response;
    }

    public function setResponseData($data)
    {
        $this->response = new Response($data, $this);
        return $this;
    }

    public function getStatusList()
    {
        return $this->status;
    }

    public function getPaidConst()
    {
        return self::STATUS_PAID;
    }

    public function getPreauthConst()
    {
        return self::STATUS_PREAUTHORIZED;
    }

    public function getCanceledConst()
    {
        return self::STATUS_CANCELED;
    }

    public function getError($id)
    {
        return !empty($this->errors[$id]) ? $this->errors[$id] : 'unknown';
    }

    /**
     * Returns the name of the orderId parameter usually sent by GET/POST
     */
    abstract public function getOrderIdParamName();

    /**
     * An array with contact keys poiting to the Eloquent Contact fields.
     *
     * @example
     *  return [
     * 'firstName' => 'firstname',
     * 'lastName' => 'lastname',
     * 'address' => 'address',
     * 'email' => 'email',
     * 'mobilePhone' => 'phone',
     * 'country' => ['country', 'name'],
     * 'county' => ['county', 'name'],
     * 'city' => 'city',
     * 'zipCode' => 'postalcode',
     * ];
     */
    abstract public function getContactKeyMappings();

    /**
     * Connect to payment processor and generates the parameters for payment,
     * in general used to redirect the client to a 3rdparty payment page.
     *
     */
    abstract public function generatePurchaseParams();

    /**
     * Gets the response (in general called in confirm callback).
     * This should call $this->setResponseData();
     */
    abstract public function response();

    /**
     * Response when Payment processor calls the callback url
     * (in general confirm_url)
     */
    abstract public function callbackOutput();

    /**
     * deposit a two way payment, preauth when order is made => deposit when order is being sent/confirmed to client
     *
     * Not mandatory.
     */
    public function deposit()
    {

    }

    /**
     * reverse a two way payment, preauth when order is made => reverse when order is canceled
     *
     * Not mandatory.
     */
    public function reverse()
    {

    }
}
