/**
  * Get payment choice and have end user confirm and place order.
  * A user can choose a simple integration method which will redirect
  * them to the confirmation page. If they put their cc details directly
  * in the form to checkout with an advanced method, the confirmation
  * page is immediately rendered.
  *
  * @return void
  */
 public function actionFinal()
 {
     $this->checkoutForm = MultiCheckoutForm::loadFromSessionOrNew();
     $arrCheckbox = array('id' => 1, 'name' => 'MultiCheckoutForm[billingSameAsShipping]', 'label' => Yii::t('checkout', 'Use my shipping address as my billing address'), 'address' => $this->checkoutForm->strShippingAddress);
     $objCart = Yii::app()->shoppingcart;
     // check to see if we have any advanced methods and if not redirect to the simple payment action
     $arrModules = $this->checkoutForm->getAimPaymentMethods();
     if (count($arrModules) < 1) {
         $this->redirect($this->createAbsoluteUrl('/checkout/paymentsimple'));
     }
     // set cardholder name to default i.e. contact name
     $this->checkoutForm->cardNameOnCard = $this->checkoutForm->contactFirstName . ' ' . $this->checkoutForm->contactLastName;
     // is an existing user changing their billing address?
     if (isset($_POST['BillingAddress']) && !isset($_POST['MultiCheckoutForm']['intBillingAddress'])) {
         $val = $_POST['BillingAddress'];
         if (is_numeric($val)) {
             if (isset($_POST['MultiCheckoutForm'])) {
                 $this->checkoutForm->attributes = $_POST['MultiCheckoutForm'];
             }
             $this->checkoutForm->intBillingAddress = $val;
             $this->checkoutForm->fillAddressFields($val);
             $arrCheckbox['id'] = $val;
             $arrCheckbox['name'] = 'MultiCheckoutForm[intBillingAddress]';
             $arrCheckbox['label'] = Yii::t('checkout', 'Use this as my billing address');
             $arrCheckbox['address'] = $this->checkoutForm->strBillingAddress;
             $arrAddresses = CustomerAddress::getActiveAddresses();
             // remove shipping address from the address array
             // to prevent someone attempting to edit it
             foreach ($arrAddresses as $key => $objAddress) {
                 if ($objAddress->id === $this->checkoutForm->intShippingAddress) {
                     unset($arrAddresses[$key]);
                     break;
                 }
             }
             $this->checkoutForm->objAddresses = $arrAddresses;
             $this->layout = '/layouts/checkout';
             $this->render('paymentaddress', array('model' => $this->checkoutForm, 'checkbox' => $arrCheckbox, 'error' => $this->formatErrors(), 'paymentFormModules' => $this->checkoutForm->getAlternativePaymentMethodsThatUseSubForms()));
         }
     } elseif (isset($_POST['Payment']) || isset($_POST['Paypal'])) {
         if (isset($_POST['MultiCheckoutForm'])) {
             $this->checkoutForm->attributes = $_POST['MultiCheckoutForm'];
             if (_xls_get_conf('SHIP_SAME_BILLSHIP') == 1) {
                 $this->checkoutForm->billingSameAsShipping = 1;
             }
             // get all the active alternative / offline payment methods
             $alternatePaymentMethods = $this->checkoutForm->getAlternativePaymentMethods();
             if (array_key_exists($this->checkoutForm->paymentProvider, $alternatePaymentMethods) || isset($_POST['Paypal'])) {
                 // end user has either chosen an alternative payment method or hit the Paypal button
                 // clear sensitive data just in case
                 $this->checkoutForm->clearCCdata();
                 // set billing address to be the same as shipping so that the form passes validation
                 $this->checkoutForm->billingSameAsShipping = 1;
                 $blnBillAddressHandled = true;
                 // user chose paypal
                 if (isset($_POST['Paypal'])) {
                     $this->checkoutForm->paymentProvider = $_POST['Paypal'];
                 }
                 $this->checkoutForm->saveFormToSession();
                 // set scenario
                 if ($objCart->shipping->isStorePickup) {
                     $this->checkoutForm->setScenario('PaymentStorePickup');
                     // no customer addresses required
                 } else {
                     $this->checkoutForm->setScenario('PaymentSim');
                     // shipping address is required
                     $blnBillAddressHandled = $this->checkoutForm->updateAddressId('billing');
                     // set billing address to shipping address to pass validation
                 }
                 // validate and update payment
                 $objPayment = CartPayment::getOrCreateCartPayment();
                 if ($blnBillAddressHandled && $this->checkoutForm->validate() && $this->checkoutForm->handleSubform() && $objPayment->updateCartPayment($this->checkoutForm, $this->checkoutForm->subFormModel)) {
                     // save the passed scenario
                     $this->checkoutForm->passedScenario = $this->checkoutForm->getScenario();
                     $this->checkoutForm->saveFormToSession();
                     $this->redirect($this->createAbsoluteUrl('/checkout/confirmation'));
                 }
                 $this->checkoutForm->addErrors($objPayment->getErrors());
                 $this->publishJS('payment');
                 $this->publishJS('zippo');
                 $this->layout = '/layouts/checkout';
                 if (count($this->checkoutForm->objAddresses) > 0) {
                     $this->render('paymentaddress', array('model' => $this->checkoutForm, 'checkbox' => $arrCheckbox, 'error' => $this->formatErrors(), 'paymentFormModules' => $this->checkoutForm->getAlternativePaymentMethodsThatUseSubForms()));
                 } else {
                     $this->render('payment', array('model' => $this->checkoutForm, 'error' => $this->formatErrors(), 'paymentFormModules' => $this->checkoutForm->getAlternativePaymentMethodsThatUseSubForms()));
                 }
             } else {
                 // if we are here, the end user has entered their card details directly (AIM)
                 // ensure form is populated with billing address
                 if (isset($this->checkoutForm->intBillingAddress)) {
                     $this->checkoutForm->fillAddressFields($this->checkoutForm->intBillingAddress);
                     $this->checkoutForm->billingSameAsShipping = null;
                 }
                 // payment processors require the cardNumber formatted as an
                 // actual number so remove whitespace from the cardNumber
                 $this->checkoutForm->cardNumber = _xls_number_only($this->checkoutForm->cardNumber);
                 $this->checkoutForm->cardNumberLast4 = substr($this->checkoutForm->cardNumber, -4);
                 // only the last 4 digits
                 // prevent an exception if cardExpiry is left blank
                 if (isset($this->checkoutForm->cardExpiry) && $this->checkoutForm->cardExpiry !== '') {
                     $arrCardExpiry = explode('/', $this->checkoutForm->cardExpiry);
                     $this->checkoutForm->cardExpiryMonth = $arrCardExpiry[0];
                     $this->checkoutForm->cardExpiryYear = $arrCardExpiry[1] + 2000;
                 }
                 // set scenario
                 if ($objCart->shipping->isStorePickup) {
                     $this->checkoutForm->setScenario('PaymentStorePickupCC');
                     // only billing address required
                 } else {
                     $this->checkoutForm->setScenario('Payment');
                     // shipping and billing address required
                 }
                 // validate the form
                 $objPayment = CartPayment::getOrCreateCartPayment();
                 if ($this->checkoutForm->updateAddressId('billing') && $this->checkoutForm->validate() && $objPayment->updateCartPayment($this->checkoutForm)) {
                     $this->layout = '/layouts/checkout-confirmation';
                     $this->render('confirmation', array('model' => $this->checkoutForm, 'cart' => Yii::app()->shoppingcart, 'shippingEstimatorOptions' => $this->_getShippingEstimatorOptions(), 'error' => $this->formatErrors()));
                 } else {
                     $this->checkoutForm->addErrors($objPayment->getErrors());
                     // clear sensitive data and force user to re-enter them
                     $this->checkoutForm->clearCCdata();
                     $this->publishJS('payment');
                     $this->publishJS('zippo');
                     $this->layout = '/layouts/checkout';
                     if (count($this->checkoutForm->objAddresses) > 0) {
                         $this->render('paymentaddress', array('model' => $this->checkoutForm, 'checkbox' => $arrCheckbox, 'error' => $this->formatErrors(), 'paymentFormModules' => $this->checkoutForm->getAlternativePaymentMethodsThatUseSubForms()));
                     } else {
                         $this->render('payment', array('model' => $this->checkoutForm, 'error' => $this->formatErrors(), 'paymentFormModules' => $this->checkoutForm->getAlternativePaymentMethodsThatUseSubForms()));
                     }
                 }
             }
         }
     } elseif (isset($_POST['Confirmation'])) {
         $haveCartItemsBeenUpdated = false;
         if (isset($_POST['MultiCheckoutForm'])) {
             $this->checkoutForm->attributes = $_POST['MultiCheckoutForm'];
             if ($objCart->shipping->isStorePickup) {
                 $this->checkoutForm->setScenario('ConfirmationStorePickupCC');
                 // only billing address required
             } else {
                 $this->checkoutForm->setScenario('Confirmation');
                 // shipping and billing address required
             }
             // validate form and cart
             if ($this->checkoutForm->updateCartCustomerId() && $this->checkoutForm->validate()) {
                 // if the cart was modified stop checkout and re-render the page with the message to the end user
                 if (Yii::app()->shoppingcart->wasCartModified === false) {
                     // cart is as we expect, continue
                     $result = $this->executeCheckoutProcess();
                     if (isset($result['success']) && isset($result['cartlink'])) {
                         // send user to receipt
                         $this->redirect($this->createAbsoluteUrl("/checkout/thankyou/" . $result['cartlink']));
                     }
                 }
             }
         }
         $this->layout = '/layouts/checkout-confirmation';
         $this->render('confirmation', array('model' => $this->checkoutForm, 'cart' => Yii::app()->shoppingcart, 'shippingEstimatorOptions' => $this->_getShippingEstimatorOptions(), 'error' => $this->formatErrors(), 'recalculateShippingOnLoad' => Yii::app()->shoppingcart->wasCartModified));
     } else {
         $this->layout = '/layouts/checkout';
         $this->publishJS('payment');
         $this->publishJS('zippo');
         // clear sensitive data
         $this->checkoutForm->clearCCdata();
         // existing user with existing addresses
         if (count($this->checkoutForm->objAddresses) > 0) {
             $arrCheckbox['name'] = 'MultiCheckoutForm[intBillingAddress]';
             // if the billing address was defined before, set the checkbox label
             if (isset($this->checkoutForm->intBillingAddress) && $this->checkoutForm->intBillingAddress !== $this->checkoutForm->intShippingAddress) {
                 $arrCheckbox['label'] = Yii::t('checkout', 'Use this as my billing address');
             }
             // get up to date address info
             $arrAddresses = CustomerAddress::getActiveAddresses();
             // find the selected address id
             $selectedAddressId = null;
             $blnDefaultBilling = true;
             if (isset($_POST['BillingAddress']) === false && isset($this->checkoutForm->intBillingAddress) === false) {
                 // Check to see if the customer has a default billing address set
                 if ($objCart->customer->default_billing_id !== null) {
                     $objTemp = $objCart->customer->defaultBilling;
                     if ($objTemp->active == 1) {
                         $selectedAddressId = $objTemp->id;
                     } else {
                         $blnDefaultBilling = false;
                     }
                 } else {
                     $blnDefaultBilling = false;
                 }
                 if ($blnDefaultBilling === false) {
                     // No default billing address available so just use the first address in the array
                     $objAddress = current($arrAddresses);
                     $selectedAddressId = $objAddress->id;
                 }
             } else {
                 $selectedAddressId = $this->checkoutForm->intShippingAddress;
             }
             // remove the selected address from the array
             foreach ($arrAddresses as $key => $objAddress) {
                 if ($objAddress->id === $selectedAddressId) {
                     $arrCheckbox['id'] = $objAddress->id;
                     $arrCheckbox['address'] = _xls_string_address($objAddress);
                     break;
                 }
             }
             // remove the shipping address from the array
             foreach ($arrAddresses as $key => $objAddress) {
                 if ($objAddress->id === $this->checkoutForm->intShippingAddress) {
                     unset($arrAddresses[$key]);
                     break;
                 }
             }
             $this->checkoutForm->objAddresses = $arrAddresses;
             $this->checkoutForm->saveFormToSession();
             $this->render('paymentaddress', array('model' => $this->checkoutForm, 'checkbox' => $arrCheckbox, 'error' => $this->formatErrors(), 'paymentFormModules' => $this->checkoutForm->getAlternativePaymentMethodsThatUseSubForms()));
         } else {
             $this->render('payment', array('model' => $this->checkoutForm, 'error' => $this->formatErrors(), 'paymentFormModules' => $this->checkoutForm->getAlternativePaymentMethodsThatUseSubForms()));
         }
     }
 }