<?php 
/**
 * Paypal Class 
 * 
 */
require_once  __DIR__  . '/PayPal-PHP-SDK/autoload.php';

class Paypal{
    const DEFAULT_EMAIL_SUBJECT = "You have a Payout!";
    const DEFAULT_SENDER_NOTE = "Thanks for your patronage!";
    const DEFAULT_CURRENCY = "USD";
    const PAYOUT = "payout";
    const EMAIL_TYPE = "EMAIL";
    const PHONE_TYPE = "PHONE";
    const PAYPAL_ID_TYPE = "PAYPAL_ID";
    const SUCCESS_STATUS = "Success";
    const FAIL_STATUS = "Fail";

    private $_apiContext;
    private $_type;
    
    private $_mandateFields = array(
                                "payout" => array("request_id","receiver","amount")
                                );


    public function __construct($param=array()) {
        if( ENVIRONMENT == 'development' ) {
            $config = parse_ini_file( "custom_config_dev.ini" );
            $mode = 'Sandbox';
        } else {
            $config = parse_ini_file( "custom_config_production.ini" );
            $mode = 'live';
        }
        $client_id = $config['paypal'][''.$param['website'].'-client_id'];
        $client_secret = $config['paypal'][''.$param['website'].'-client_secret'];
        $this->_apiContext =  new \PayPal\Rest\ApiContext(
                                    new \PayPal\Auth\OAuthTokenCredential(
                                        $client_id,
                                        $client_secret
                                    )
                                );
        $configration = array(
                    'mode' => $mode
                );
        $this->_apiContext->setConfig($configration);
    }
    /**
     * 
     * @param array $param
     * $param = array(
     *              "request_id"=>Unique request ID //Mandate Unique ID
     *              "email_subject"=>"Any string" //optional The subject line for the email that PayPal sends when payment for a payout item completes
     *              "receiver"=>"Email id/Phone number" //Mandate Any valid Email Id and Phone Number
     *              "amount"=> "Number/Float" // Mandate
     *              "currency"=> "USD" // Optional
     *              "sender_note" => "Any string messgae" // Optional
     *              "sender_item_id"=>"any Id "
     *              )
     * 
     */
    public function payout($param) {
        
        if($this->_validateInput($param, self::PAYOUT)){
            $subject = empty($param['email_subject']) ? self::DEFAULT_EMAIL_SUBJECT : $param['email_subject'];
            $payouts = new \PayPal\Api\Payout();
            $senderBatchHeader = new \PayPal\Api\PayoutSenderBatchHeader();
            $senderBatchHeader->setSenderBatchId($param['request_id'])->setEmailSubject($subject);
            
            $sender_note = empty($param['sender_note']) ? self::DEFAULT_SENDER_NOTE : $param['sender_note'];
            $currency = empty($param['currency']) ? self::DEFAULT_CURRENCY : $param['currency'];
            $amount = $param['amount'];
            $sender_item_id = empty($param['sender_item_id']) ? time() : $param['sender_item_id'];
            $currencyInput = json_encode(array("value"=>$amount,"currency"=>$currency));
            
            $senderItem = new \PayPal\Api\PayoutItem();
            $senderItem->setRecipientType($this->_type)
                ->setNote($sender_note)
                ->setReceiver($param['receiver'])
                ->setSenderItemId($sender_item_id)
                ->setAmount(new \PayPal\Api\Currency($currencyInput));
            $payouts->setSenderBatchHeader($senderBatchHeader)->addItem($senderItem);
            
            try {
                $output = $payouts->create(array(),$this->_apiContext);
                $response = $output->toArray();
            } catch (PayPal\Exception\PayPalConnectionException $ex) {
                $errorObj = json_decode($ex->getData(),true);
                return array("status"=> self::FAIL_STATUS,"response"=>$errorObj['details'],"error"=>$errorObj['message']);
            }
            return array("status"=> self::SUCCESS_STATUS,"response"=>$response['batch_header'],"error"=>NULL);
        }else{
            return array("status"=> self::FAIL_STATUS,"error"=>"Input Validation Fails","response"=>NULL);
        }
        
    }
    /**
     * Get Batch status
     * @param type $batch_id
     * @return type
     */
    public function getPayoutStatus($batch_id) {
        try {
            $output = \PayPal\Api\Payout::get($batch_id, $this->_apiContext);
            $response = $output->toArray();   
        } catch (PayPal\Exception\PayPalConnectionException $ex) {
            $errorObj = json_decode($ex->getData(),true);
            return array("status"=> self::FAIL_STATUS,"response"=>$errorObj['details'],"error"=>$errorObj['message']);
        }
        return array("status"=> self::SUCCESS_STATUS,"response"=>$response,"error"=>NULL);
    }
    /**
     * 
     * @param type $param
     * @param type $methodType
     */
    public function _validateInput($param,$methodType) {
        $mandateFields = $this->_mandateFields[$methodType];
        if(empty($mandateFields))
            return true;
        $invalid = 0;
        foreach ($mandateFields as $field) {
            if(!isset($param[$field]) || empty($param[$field])){
                $invalid = 1;
                break;
            }
        }
        
        if($methodType == self::PAYOUT){
            if(isset($param['receiver']) && !empty($param['receiver'])){
                if(filter_var($param['receiver'], FILTER_VALIDATE_EMAIL)){
                    $this->_type = self::EMAIL_TYPE;
                }elseif(preg_match("/^[0-9]{10}$/", $param['receiver'])){
                    $this->_type = self::PHONE_TYPE;
                }else{
                    $invalid = 1;
                }
            }else{
                $invalid = 1;
            }
        }
        
        return ($invalid) ? FALSE : TRUE;
    }
}