<?php

  /**
   * Payments implementation that can be attached to any object
   *
   * @package angie.frameworks.payments
   * @subpackage models
   */
  abstract class IPaymentsImplementation {
    
    /**
     * Parent object
     *
     * @var Invoice
     */
    protected $object;
    
    /**
     * Construct paymetns helper
     *
     * @param IPayments $object
     */
    function __construct(IPayments $object) {
      $this->object = $object;
    } // __construct
    
    /**
     * Determine if payments are enabled
     * 
     * @return boolean
     */
    function isEnabled() {
      $allow_payment = ConfigOptions::getValue('allow_payments');
      $object_payment = $this->object->getAllowPayments();
      $payment_for_object = ConfigOptions::getValue('allow_payments_for_invoice');
      return $allow_payment > 0 && (($object_payment == Payment::USE_SYSTEM_DEFAULT && $payment_for_object > 0) || $object_payment > 0); 
    } //isEnabled
    
    /**
     * Return true if partial payment enabled
     * 
     * @return boolean
     */
    function isPartialEnabled() {
      $allow_payment = ConfigOptions::getValue('allow_payments');
      $object_payment = $this->object->getAllowPayments();
      $payment_for_object = ConfigOptions::getValue('allow_payments_for_invoice');
      return $allow_payment > 1 && (($object_payment == Payment::USE_SYSTEM_DEFAULT && $payment_for_object > 1) || $object_payment > 1); 
    } //isPartialEnabled
    
    /**
     * Returns true if $user can make a new payment to this object
     *
     * @param IUser $user
     * @return boolean
     */
    function canMake(User $user) {
      return $user->isFinancialManager() || (Invoices::canAccessCompanyInvoices($user, $this->object->getCompany()) && $this->isEnabled() && $this->hasEnabledGateways());
    } //canMake
    
     /**
     * Returns true if $user can edit payment to this object
     *
     * @param IUser $user
     * @return boolean
     */
    function canEdit(User $user) {
      return $user->isFinancialManager();
    } //canEdit
    
     /**
     * Returns true if $user can delete payment from this object
     *
     * @param IUser $user
     * @return boolean
     */
    function canDelete(User $user) {
      return $user->isFinancialManager();
    } //canDelete
    
    /**
     * Returns true if $user can view payment details from this object
     *
     * @param IUser $user
     * @return boolean
     */
    function canView(User $user) {
      return $user->isFinancialManager();
    } //canView
    
    /**
     * Return true if user can make partial payments to this object
     * 
     * @param $user
     * @return $boolean
     */
    function canMakePartial() {
      return $this->isPartialEnabled();
    } //canMakePartial
    
    /**
     * Returns true if there is defined payment gateway in the system
     * 
     * @return boolean
     */
    function hasDefinedGateways() {
      return PaymentGateways::findAllCurrencySupported($this->object->getCurrencyCode());
    } //hasDefinedGateways
    
    /**
     * Returns true if there is enabled gateways, otherwise return false
     * 
     * @return boolean
     */
    function hasEnabledGateways() {
      return boolval(PaymentGateways::findEnabled());
    }//hasEnabledGateways
    
    /**
     * List of proceeded payments
     * 
     * @var array
     */
    private $gateway_payments = false;
    
    /**
     * Return payments made to the parent object
     * 
     * @return array
     */
    function getPayments() {
      if($this->gateway_payments === false) {
        $this->gateway_payments = Payments::getSliceByObject($this->object);
      } //if
      
      return $this->gateway_payments;
    } //getPayments
    
    /**
     * Return total number of payments for this object
     */
    function getTotalPayments() {
      return Payments::getTotalNumberByObject($this->object);
    } //getTotalPayments
    
    /**
     * Return total amount paied for parent object
     */
    function getPaidAmount() {
      return (float) DB::executeFirstCell("SELECT SUM(amount) AS 'amount_paid' FROM " . TABLE_PREFIX . 'payments WHERE parent_id = ? AND parent_type = ? AND status = ?', $this->object->getId(), get_class($this->object), Payment::STATUS_PAID);
    } //getPaidAmount

    // ---------------------------------------------------
    //  Gag
    // ---------------------------------------------------

    /**
     * Notifications gagged flag
     *
     * @var bool
     */
    private $gagged = false;

    /**
     * Returns true if this implementation is gagged
     *
     * @return bool
     */
    function isGagged() {
      return $this->gagged;
    } // isGagged

    /**
     * Gag notifications
     */
    function gag() {
      $this->gagged = true;
    } // gag

    /**
     * Ungag notifications
     */
    function ungag() {
      $this->gagged = false;
    } // ungag
    
    // ---------------------------------------------------
    //  URL-s
    // ---------------------------------------------------
    
    /**
     * Return make payment URL for parent object
     *
     * @param integer $amount
     * @return string
     */
    function getUrl() {
      return Router::assemble($this->object->getRoutingContext() . '_payments', $this->object->getRoutingContextParams());
    } // getUrl
    
    /**
     * Return make payment URL
     * 
     * @param float $amount
     * @return string
     */
    function getAddUrl($amount = null) {
      $params = $this->object->getRoutingContextParams();
      
      if($amount) {
        if(is_array($params)) {
          $params['amount'] = $amount;
        } else {
          $params = array('amount' => $amount);
        } // if
      } // if
      return Router::assemble($this->object->getRoutingContext() . '_payments_add', $params);
    } // getAddUrl
    
    /**
     * Delete all payments for this object
     *
     * @return boolean
     */
    function delete() {
      return DB::execute('DELETE FROM ' . TABLE_PREFIX . 'payments WHERE parent_type = ? AND parent_id = ?', get_class($this->object), $this->object->getId());
    }//delete
  
  }