/**
  * Calculate the membership status.
  *
  * Calculate status for the membership verifying the start date,
  * trial exire date and expire date.
  *
  * @since  1.0.0
  * @internal
  *
  * @param string $set_status The set status to compare.
  * @return string The calculated status.
  */
 protected function calculate_status($set_status = null, $debug = false)
 {
     /**
      * Documented in check_membership_status()
      *
      * @since  1.0.0
      */
     if (MS_Plugin::get_modifier('MS_LOCK_SUBSCRIPTIONS')) {
         return $set_status;
     }
     $membership = $this->get_membership();
     $calc_status = null;
     $debug_msg = array();
     $check_trial = $this->is_trial_eligible();
     if (!empty($this->payments)) {
         /*
          * The user already paid for this membership, so don't check for
          * trial status anymore
          */
         $check_trial = false;
     }
     // If the start-date is not reached yet, then set membership to Pending.
     if (!$calc_status && !empty($this->start_date) && strtotime($this->start_date) > strtotime(MS_Helper_Period::current_date())) {
         $calc_status = self::STATUS_WAITING;
         $debug_msg[] = '[WAITING: Start-date not reached]';
     } elseif (!$calc_status && $debug) {
         $debug_msg[] = '[Not WAITING: No start-date or start-date reached]';
     }
     if ($check_trial) {
         if (!$calc_status && strtotime($this->trial_expire_date) >= strtotime(MS_Helper_Period::current_date())) {
             $calc_status = self::STATUS_TRIAL;
             $debug_msg[] = '[TRIAL: Trial-Expire date not reached]';
         } elseif (!$calc_status && $debug) {
             $debug_msg[] = '[Not TRIAL: Trial-Expire date reached]';
         }
         if (!$calc_status && strtotime($this->trial_expire_date) < strtotime(MS_Helper_Period::current_date())) {
             $calc_status = self::STATUS_TRIAL_EXPIRED;
             $debug_msg[] = '[TRIAL-EXPIRED: Trial-Expire date reached]';
         } elseif (!$calc_status && $debug) {
             $debug_msg[] = '[Not TRIAL-EXPIRED: Trial-Expire date not reached]';
         }
     } elseif (!$calc_status && $debug) {
         $debug_msg[] = '[Skipped TRIAL status]';
     }
     // Status an only become active when added by admin or invoice is paid.
     $can_activate = false;
     if ('admin' == $this->gateway_id) {
         $can_activate = true;
         $debug_msg[] = '[Can activate: Admin gateway]';
     } elseif ($membership->is_free()) {
         $can_activate = true;
         $debug_msg[] = '[Can activate: Free membership]';
     } elseif (!empty($this->source)) {
         $can_activate = true;
         $debug_msg[] = '[Can activate: Imported subscription]';
     } else {
         $valid_payment = false;
         // Check if there is *any* payment, no matter what height.
         foreach ($this->get_payments() as $payment) {
             if ($payment['amount'] > 0) {
                 $valid_payment = true;
                 $debug_msg[] = '[Can activate: Payment found]';
                 break;
             }
         }
         if (!$valid_payment) {
             // Check if any invoice was paid already.
             for ($ind = $this->current_invoice_number; $ind > 0; $ind -= 1) {
                 $invoice = MS_Model_Invoice::get_invoice($this->id, $ind);
                 if (!$invoice) {
                     continue;
                 }
                 if ($invoice->uses_trial) {
                     continue;
                 }
                 if ($invoice->is_paid()) {
                     $valid_payment = true;
                     $debug_msg[] = '[Can activate: Paid invoice found]';
                     break;
                 }
             }
         }
         if (!$valid_payment) {
             // Check if the current invoice is free.
             $invoice = $this->get_current_invoice();
             if (0 == $invoice->total) {
                 $valid_payment = true;
             }
         }
         if ($valid_payment) {
             $can_activate = true;
         }
         if (!$can_activate && $debug) {
             $debug_msg[] = sprintf('[Can not activate: Gateway: %s; Price: %s; Invoice: %s]', $this->gateway_id, $membership->price, $invoice->total);
         }
     }
     if ($can_activate) {
         // Permanent memberships grant instant access, no matter what.
         if (!$calc_status && MS_Model_Membership::PAYMENT_TYPE_PERMANENT == $membership->payment_type) {
             $calc_status = self::STATUS_ACTIVE;
             $debug_msg[] = '[ACTIVE(1): Payment-type is permanent]';
         } elseif (!$calc_status && $debug) {
             $debug_msg[] = '[Not ACTIVE(1): Payment-type is not permanent]';
         }
         // If expire date is empty and Active-state is requests then use active.
         if (!$calc_status && empty($this->expire_date) && self::STATUS_ACTIVE == $set_status) {
             $calc_status = self::STATUS_ACTIVE;
             $debug_msg[] = '[ACTIVE(2): Expire date empty and active requested]';
         } elseif (!$calc_status && $debug) {
             $debug_msg[] = '[Not ACTIVE(2): Expire date set or wrong status-request]';
         }
         // If expire date is not reached then membership obviously is active.
         if (!$calc_status && !empty($this->expire_date) && strtotime($this->expire_date) >= strtotime(MS_Helper_Period::current_date())) {
             $calc_status = self::STATUS_ACTIVE;
             $debug_msg[] = '[ACTIVE(3): Expire date set and not reached]';
         } elseif (!$calc_status && $debug) {
             $debug_msg[] = '[Not ACTIVE(3): Expire date set and reached]';
         }
     } elseif (!$calc_status && self::STATUS_PENDING == $this->status) {
         // Invoice is not paid yet.
         $calc_status = self::STATUS_PENDING;
         $debug_msg[] = '[PENDING: Cannot activate pending subscription]';
     } elseif (!$calc_status && $debug) {
         $debug_msg[] = '[Not ACTIVE/PENDING: Cannot activate subscription]';
     }
     // If no other condition was true then the expire date was reached.
     if (!$calc_status) {
         $calc_status = self::STATUS_EXPIRED;
         $debug_msg[] = '[EXPIRED: Default status]';
     }
     // Did the user cancel the membership?
     $cancel_it = self::STATUS_CANCELED == $set_status || self::STATUS_CANCELED == $this->status && self::STATUS_ACTIVE != $set_status && self::STATUS_TRIAL != $set_status;
     if ($cancel_it) {
         /*
          * When a membership is cancelled then it will stay "Cancelled"
          * until the expiration date is reached. A user has access to the
          * contents of a cancelled membership until it expired.
          */
         if (self::STATUS_EXPIRED == $calc_status) {
             // Membership has expired. Finally deactivate it!
             // (possibly it was cancelled a few days earlier)
             $calc_status = self::STATUS_DEACTIVATED;
         } elseif (self::STATUS_TRIAL_EXPIRED == $calc_status) {
             // Trial period has expired. Finally deactivate it!
             $calc_status = self::STATUS_DEACTIVATED;
         } elseif (self::STATUS_TRIAL == $calc_status) {
             // User can keep access until trial period finishes...
             $calc_status = self::STATUS_CANCELED;
         } elseif (MS_Model_Membership::PAYMENT_TYPE_PERMANENT == $membership->payment_type) {
             // This membership has no expiration-time. Deactivate it!
             $calc_status = self::STATUS_DEACTIVATED;
         } elseif (self::STATUS_WAITING == $calc_status) {
             // The membership did not yet start. Deactivate it!
             $calc_status = self::STATUS_DEACTIVATED;
         } elseif (!$this->expire_date) {
             // Membership without expire date cannot be cancelled. Deactivate it!
             $calc_status = self::STATUS_DEACTIVATED;
         } else {
             // Wait until the expiration date is reached...
             $calc_status = self::STATUS_CANCELED;
         }
     }
     if ($debug) {
         // Intended debug output, leave it here.
         lib3()->debug->dump($debug_msg);
     }
     return apply_filters('membership_model_relationship_calculate_status', $calc_status, $this);
 }