/**
  * Updates payment status of basket and of corresponding subscriptions if there is a change in status
  *
  * @param  cbpaidPaymentBasket        $paymentBasket         Basket
  * @param  string                     $eventType             type of event (paypal type): 'web_accept', 'subscr_payment', 'subscr_signup', 'subscr_modify', 'subscr_eot', 'subscr_cancel', 'subscr_failed'
  * @param  string                     $paymentStatus         new status (Completed, RegistrationCancelled)
  * @param  cbpaidPaymentNotification  $notification          notification object of the payment
  * @param  int                        $occurrences           renewal occurrences
  * @param  int                        $autorecurring_type    0: not auto-recurring, 1: auto-recurring without payment processor notifications, 2: auto-renewing with processor notifications updating $expiry_date
  * @param  int                        $autorenew_type        0: not auto-renewing (manual renewals), 1: asked for by user, 2: mandatory by configuration
  * @param  boolean|string             $txnIdMultiplePaymentDates  FALSE: unique txn_id for each payment, TRUE: same txn_id can have multiple payment dates, additionally: 'SINGLEPAYMENT' will not look at txn_id at all
  * @param  boolean                    $storePaymentRecord   TRUE: normal case, create payment record if needed. FALSE: offline case where pending payment should not create a payment record.
  * @return void
  */
 public function updatePaymentStatus($paymentBasket, $eventType, $paymentStatus, &$notification, $occurrences, $autorecurring_type, $autorenew_type, $txnIdMultiplePaymentDates, $storePaymentRecord = true)
 {
     global $_CB_framework, $_PLUGINS;
     $pluginsLoaded = false;
     $basketUpdateNulls = false;
     $previousUnifiedStatus = $this->mapPaymentStatus($paymentBasket->payment_status);
     $unifiedStatus = $this->mapPaymentStatus($paymentStatus);
     // get all related subscriptions being paid by this basket:
     $subscriptions = $paymentBasket->getSubscriptions();
     $thisIsReferencePayment = false;
     $user = CBuser::getUserDataInstance((int) $paymentBasket->user_id);
     if ($paymentBasket->payment_status != $paymentStatus || $unifiedStatus == 'Partially-Refunded' || $autorecurring_type) {
         if ($paymentStatus && (in_array($eventType, array('web_accept', 'subscr_payment', 'subscr_signup')) || in_array($unifiedStatus, array('Reversed', 'Refunded', 'Partially-Refunded')))) {
             $paymentBasket->payment_status = $paymentStatus;
         }
         if (in_array($eventType, array('subscr_payment', 'subscr_signup'))) {
             $paymentBasket->recurring = 1;
         }
         if ($autorecurring_type == 0 && in_array($unifiedStatus, array('Completed', 'Processed', 'FreeTrial'))) {
             $paymentBasket->mc_amount1 = null;
             $paymentBasket->mc_amount3 = null;
             $paymentBasket->period1 = null;
             $paymentBasket->period3 = null;
             $basketUpdateNulls = true;
         }
         // if (count($subscriptions) >= 1) {
         $now = $_CB_framework->now();
         $completed = false;
         $thisIsReferencePayment = false;
         $reason = null;
         switch ($unifiedStatus) {
             case 'FreeTrial':
             case 'Completed':
             case 'Processed':
                 // this includes Canceled_Reversal !!! :
                 if ($unifiedStatus == 'FreeTrial') {
                     $paymentBasket->payment_status = 'Completed';
                 }
                 if ($unifiedStatus == 'FreeTrial' || $unifiedStatus == 'Completed') {
                     if ($notification->payment_date) {
                         $time_completed = cbpaidTimes::getInstance()->gmStrToTime($notification->payment_date);
                     } else {
                         $time_completed = $now;
                     }
                     $paymentBasket->time_completed = Application::Database()->getUtcDateTime($time_completed);
                     $completed = true;
                 }
                 if ($paymentStatus == 'Canceled_Reversal') {
                     $paymentBasket->payment_status = 'Completed';
                 }
                 if (is_object($notification) && isset($notification->txn_id)) {
                     // real payment with transaction id: store as reference payment if not already stored:
                     $thisIsReferencePayment = $this->_storePaymentOnce($paymentBasket, $notification, $now, $txnIdMultiplePaymentDates, 'Updating payment record because of new status of payment basket: ' . $unifiedStatus . ($paymentStatus != $unifiedStatus ? ' (new gateway-status: ' . $paymentStatus . ')' : '') . ' because of event received: ' . $eventType . '. Previous status was: ' . $previousUnifiedStatus);
                 } else {
                     // Free trials don't have a notification:
                     $thisIsReferencePayment = true;
                 }
                 if ($thisIsReferencePayment) {
                     // payment not yet processed:
                     $autorenewed = $paymentBasket->recurring == 1 && $unifiedStatus == 'Completed' && $previousUnifiedStatus == 'Completed';
                     for ($i = 0, $n = count($subscriptions); $i < $n; $i++) {
                         $reason = $autorenewed ? 'R' : $subscriptions[$i]->_reason;
                         $subscriptions[$i]->activate($user, $now, $completed, $reason, $occurrences, $autorecurring_type, $autorenew_type, $autorenewed ? 1 : 0);
                     }
                 }
                 break;
             case 'RegistrationCancelled':
             case 'Reversed':
             case 'Refunded':
             case 'Unsubscribed':
                 if ($unifiedStatus == 'RegistrationCancelled') {
                     if (!($previousUnifiedStatus == 'NotInitiated' || $previousUnifiedStatus === 'Pending' && $paymentBasket->payment_method === 'offline')) {
                         return;
                     }
                 }
                 for ($i = 0, $n = count($subscriptions); $i < $n; $i++) {
                     $reason = $subscriptions[$i]->_reason;
                     if ($reason != 'R' || in_array($unifiedStatus, array('Reversed', 'Refunded'))) {
                         // Expired and Cancelled as well as Partially-Refunded are not reverted !		//TBD: really revert on refund everything ? a plan param would be nice here
                         if (!in_array($previousUnifiedStatus, array('Pending', 'In-Progress', 'Denied', 'Reversed', 'Refunded')) && in_array($subscriptions[$i]->status, array('A', 'R', 'I')) && !$subscriptions[$i]->hasPendingPayment($paymentBasket->id)) {
                             // not a cancelled or denied renewal:
                             $subscriptions[$i]->revert($user, $unifiedStatus);
                         }
                     }
                 }
                 if ($unifiedStatus == 'RegistrationCancelled') {
                     $paymentBasket->historySetMessage('Payment basket deleted because the subscriptions and payment got cancelled');
                     $paymentBasket->delete();
                     // deletes also payment_Items
                 }
                 $paidUserExtension = cbpaidUserExtension::getInstance($paymentBasket->user_id);
                 $subscriptionsAnyAtAll = $paidUserExtension->getUserSubscriptions('');
                 $params = cbpaidApp::settingsParams();
                 $createAlsoFreeSubscriptions = $params->get('createAlsoFreeSubscriptions', 0);
                 if (count($subscriptionsAnyAtAll) == 0 && !$createAlsoFreeSubscriptions) {
                     $user = new UserTable();
                     $id = (int) cbGetParam($_GET, 'user');
                     $user->load((int) $id);
                     if ($user->id && $user->block == 1) {
                         $user->delete(null);
                     }
                 }
                 break;
             case 'Denied':
             case 'Pending':
                 if ($unifiedStatus == 'Denied') {
                     // In fact when denied, it's the case as if the user attempted payment but failed it: He should be able to re-try: So just store the payment as denied for the records.
                     if ($eventType == 'subscr_failed' || $eventType == 'subscr_cancel' && $autorecurring_type != 2) {
                         // special case of a failed attempt:
                         // or this is the final failed attempt of a basket with notifications:
                         break;
                     }
                 }
                 if ($previousUnifiedStatus == 'Completed') {
                     return;
                     // do not change a Completed payment as it cannot become Pending again. If we get "Pending" after "Completed", it is a messages chronological order mistake.
                 }
                 break;
             case 'In-Progress':
             case 'Partially-Refunded':
             default:
                 break;
         }
         if ($eventType == 'subscr_cancel') {
             if (!in_array($unifiedStatus, array('Denied', 'Reversed', 'Refunded', 'Unsubscribed'))) {
                 for ($i = 0, $n = count($subscriptions); $i < $n; $i++) {
                     $subscriptions[$i]->autorecurring_cancelled($user, $unifiedStatus, $eventType);
                 }
             }
         }
         for ($i = 0, $n = count($subscriptions); $i < $n; $i++) {
             $subscriptions[$i]->notifyPaymentStatus($unifiedStatus, $previousUnifiedStatus, $paymentBasket, $notification, $now, $user, $eventType, $paymentStatus, $occurrences, $autorecurring_type, $autorenew_type);
         }
         if (in_array($unifiedStatus, array('Denied', 'Reversed', 'Refunded', 'Partially-Refunded', 'Pending', 'In-Progress'))) {
             $thisIsReferencePayment = $this->_storePaymentOnce($paymentBasket, $notification, $now, $txnIdMultiplePaymentDates, 'Updating payment record because of new status of payment basket: ' . $unifiedStatus . ($paymentStatus != $unifiedStatus ? ' (new gateway-status: ' . $paymentStatus . ')' : '') . ' because of event received: ' . $eventType . '. Previous status was: ' . $previousUnifiedStatus);
         }
         // }
         foreach ($paymentBasket->loadPaymentTotalizers() as $totalizer) {
             $totalizer->notifyPaymentStatus($thisIsReferencePayment, $unifiedStatus, $previousUnifiedStatus, $paymentBasket, $notification, $now, $user, $eventType, $paymentStatus, $occurrences, $autorecurring_type, $autorenew_type, $txnIdMultiplePaymentDates);
         }
         if (!in_array($unifiedStatus, array('RegistrationCancelled'))) {
             if ($thisIsReferencePayment && in_array($unifiedStatus, array('Completed', 'Processed'))) {
                 $paymentBasket->setPaidInvoiceNumber($reason);
             }
             $paymentBasket->historySetMessage('Updating payment basket ' . ($paymentStatus !== null ? 'status: ' . $unifiedStatus . ($paymentStatus != $unifiedStatus ? ' (new gateway-status: ' . $paymentStatus . ')' : '') : '') . ' because of event received: ' . $eventType . ($paymentStatus !== null ? '. Previous status was: ' . $previousUnifiedStatus : ''));
             $paymentBasket->store($basketUpdateNulls);
         } else {
             //TDB ? : $paymentBasket->delete(); in case of RegistrationCancelled done above, but should be done in case of FreeTrial ? (could be a param in future)
         }
         if (!in_array($unifiedStatus, array('Completed', 'Processed')) || $thisIsReferencePayment) {
             $_PLUGINS->loadPluginGroup('user', 'cbsubs.');
             $_PLUGINS->loadPluginGroup('user/plug_cbpaidsubscriptions/plugin');
             $pluginsLoaded = true;
             $_PLUGINS->trigger('onCPayAfterPaymentStatusChange', array(&$user, &$paymentBasket, &$subscriptions, $unifiedStatus, $previousUnifiedStatus, $occurrences, $autorecurring_type, $autorenew_type));
         }
     }
     if (!in_array($unifiedStatus, array('Completed', 'Processed')) || $thisIsReferencePayment) {
         if (!$pluginsLoaded) {
             $_PLUGINS->loadPluginGroup('user', 'cbsubs.');
             $_PLUGINS->loadPluginGroup('user/plug_cbpaidsubscriptions/plugin');
         }
         $_PLUGINS->trigger('onCPayAfterPaymentStatusUpdateEvent', array(&$user, &$paymentBasket, &$subscriptions, $unifiedStatus, $previousUnifiedStatus, $eventType, &$notification));
     }
 }