<?php

class ConfirmationAction extends CartAction {

	const OPERATION_EDIT_ORDER = 'edit-order';
    const OPERATION_CONTACT_INFORMATION = 'contact-information';
	
	public function execute($request) {
		
		$this->form = ResourceLocator::getInstance()->billingAccountService->getCreateAccountForm($this->_store->getId());
        if ($request->isMethod('post')) {
			$operation = $request->getParameter('operation');
			switch ($operation) {
                case self::OPERATION_CONTACT_INFORMATION:

                    $router = new Router();
                    $router->init(
                        array(
                            new RouterPage(self::OPERATION_CONTACT_INFORMATION),
                            new RouterPage('confirmation')
                        ),
                        new RouterPage('confirmation')
                    );
                    ResourceLocator::getInstance()->routersStack->push($router);
                    $router->next();
                    break;
				case self::OPERATION_EDIT_ORDER:
					$router = new Router();
					$router->init(
						array(
							new RouterPage('summary'),
							new RouterPage('order-details'),
							new RouterPage('confirmation')
						),
						new RouterPage('confirmation')
					);
					ResourceLocator::getInstance()->routersStack->push($router);
					$router->next();
					break;
				default:
					
					$this->form->bind($request->getParameter($this->form->getName()));
					
					try {
						
						if (!$this->form->isValid()) {
							throw new BillingFormException('TRANS_STORE_INVALID_ACCOUNT_DATA');
						}

						$accountData = $this->form->save();

						if ($customerData = sfContext::getInstance()->getUser()->getAttribute('customerData')) {
							$inputParams = array_merge($accountData, $customerData);
						} else {
							$inputParams = $accountData;
						}
						$inputParams['client_ip'] = $_SERVER['REMOTE_ADDR'];

						$shoppingSessionData = array();
						$shoppingSessionData['invoiceID'] = $this->_cart->getParameter('invoiceID', 0);
						$shoppingSessionData['shoppingItems'] = array();

						$certificateAddonsRelations = array();

						foreach (ResourceLocator::getInstance()->cart->getPurchases() as $purchase) {
							$plan = $this->_store->getPlan($purchase->getPlanId());
							$price = $plan->getPriceById($purchase->getPriceId());

							$data = false;
							switch ($plan->productType) {
								case BillingPlan::TYPE_DOMAIN:
									$data = $this->prepareDomainData($purchase, $this->_store, $plan, $price, $inputParams);
									break;
								default:
									$data = $this->prepareData($purchase, $this->_store, $plan, $price, $inputParams);
							}
							if ($data) {
								$shoppingSessionData['shoppingItems'][] = $data;
							}

							foreach ($purchase->getCertificateAddons() as $addon) {
								if (!isset($certificateAddonsRelations[$purchase->getId()])) {
									$certificateAddonsRelations[$purchase->getId()] = array();
								}
								$certificateAddonsRelations[$purchase->getId()] = $addon;
							}
						}
						foreach ($certificateAddonsRelations as $shoppingItemId => $addon) {
							$plan = $this->_store->getPlan($addon->getPlanId());
							$billingAddons = $plan->getAddons($this->_store->getId(), $addon->getCycleId());
							if (!$billingAddon = isset($billingAddons[$addon->getAddonId()]) ? $billingAddons[$addon->getAddonId()] : null) {
								continue;
							}
							$data = $this->prepareItemData($addon, $billingAddon->getPrice(), BillingPlan::TYPE_SSL_CERTIFICATE, $shoppingItemId);
							$data['certificates'] = array($this->prepareCertificateData($addon));
							$shoppingSessionData['shoppingItems'][] = $data;
						}

						if ($customer = sfContext::getInstance()->getUser()->getAttribute('customer', null)) {
							$clientId = $customer->clientID;
						} else {
							$clientId = null;
						}
						$tryBeforeBuySiteBuilderParameters = $this->_cart->getParameter('tryBeforeBuySiteBuilderParameters', array());
						$checkoutData = ResourceLocator::getInstance()->billingCheckoutService->executeCheckout(
							$this->_store->getId(),
							$shoppingSessionData,
							$inputParams,
							$clientId,
							$tryBeforeBuySiteBuilderParameters
						);
						if (isset($tryBeforeBuySiteBuilderParameters['sbOneTimeBackUrl'])) {
							$checkoutData['backUrl'] = $tryBeforeBuySiteBuilderParameters['sbOneTimeBackUrl'];
						}

						if (isset($checkoutData["fraudData"])) {
							throw new BillingFormException($checkoutData["fraudData"]["rejectMessage"]);
						}
                        if (isset($checkoutData['transaction']) && 1 != $checkoutData['transaction']['result']) {
                            if (isset($checkoutData['invoice']) && isset($checkoutData['invoice']['invoiceID'])) {
                                $this->_cart->addParameter('invoiceID', $checkoutData['invoice']['invoiceID']);
                            }
                            if ($customerData) {
                                $this->_loginJustAddedCustomer($customerData);
                            }
                            throw new BillingFormException('TRANS_PLEASE_CORRECT_OR_CHANGE_PAYMENT');
                        }

						$this->getUser()->setAttribute('checkoutData', $checkoutData);
						$this->_cart->clean();
						if ($customerData) {
							$this->_loginJustAddedCustomer($customerData);
						}
						$this->_router->next();

					} catch (BillingFormException $exception) {
						$this->errorMessage = $exception->getMessage();
					}
			}
			
		}
			
		$this->customer = sfContext::getInstance()->getUser()->getAttribute('customer', null);
		$this->customerData = sfContext::getInstance()->getUser()->getAttribute('customerData', null);
		
		sfContext::getInstance()->getConfiguration()->loadHelpers('I18N');
		
		$amount = 0;
		$totalAmount = 0;
		$prorationAmount = 0;
		$minimalCycle = null;
		
		$cartItemsData = array();
		foreach (ResourceLocator::getInstance()->cart->getItems() as $cartItemId => $cartItem) {
			$cartItemsData[$cartItemId] = array();
			
			foreach ($cartItem->getPurchases() as $purchase) {
				$subPurchases = $purchase->getPurchases(true);
				$cartItemsData[$cartItemId][$purchase->getId()] = $this->preparePurchaseViewData($purchase, $subPurchases, $amount, $totalAmount, $prorationAmount, $minimalCycle);
				$addons = array();
				foreach ($purchase->getAddons(true) as $addon) {
					$addons[] = $this->prepareAddonViewData($addon, $amount, $totalAmount, $prorationAmount, $minimalCycle);
				}
				$cartItemsData[$cartItemId][$purchase->getId()]['addons'] = $addons;
			}
			
		}
		
		$this->amount = $amount;
		$this->totalAmount = $totalAmount;
		$this->prorationAmount = $prorationAmount;
		$this->minimalCycle = $minimalCycle;
		
		$this->cartItemsData = $cartItemsData;
		
		$this->currencyId = $this->_store->currencyID;
		
		try {
			$this->company = ResourceLocator::getInstance()->billingCompanyService->getCompany($this->_store->getId());
		} catch (StoreException $exception) {
			$this->logMessage('Unable to get provider company; ' . get_class($exception) . ' message: ' . $exception->getMessage(), 'err');
		}
		
		if ($this->_store->useTermsUrl) {
			$this->externalTermsLink = $this->_store->termsUrl;
		} else {
			$this->internalTermsLink = isset($this->_store->termsText) && $this->_store->termsText ? true : false;
		}
		
	}
	
	private function preparePurchaseViewData($purchase, $subPurchases = array(), &$amount, &$totalAmount, &$prorationAmount, &$minimalCycle) {
		return PurchaseManager::preparePurchaseData($this->_store, $purchase, $subPurchases, &$amount, &$totalAmount, &$prorationAmount, &$minimalCycle);
	}
	
	private function prepareAddonViewData($addon, &$amount, &$totalAmount, &$prorationAmount, &$minimalCycle) {
		return PurchaseManager::prepareAddonData($this->_store, $addon, &$amount, &$totalAmount, &$prorationAmount, &$minimalCycle);
	}

	private function prepareData(Purchase $purchase, BillingStore $store, BillingPlan $plan, BillingPrice $price, &$inputParams) {
		
		$cycleId = $purchase->getCycleId();
		$itemData = $this->prepareItemData($purchase, $price, $plan->productType);
		$inputParams = array_merge($inputParams,(array)$purchase->getParameter('customQuestionData'));
		if ($addons = $this->prepareAddonData($purchase, $plan, $store, $cycleId, $inputParams)) {
			$itemData['children'] = $addons;
		}
		if ($plan->mayHaveDomains()) {
			
			$domains = array();
			$primaryDomainId = false;

			foreach($purchase->getOwnDomains() as $domainData) {
				$primaryDomainId = 0;
				$data = array(
					'shoppingItemsDomainsRelID' => 0,
					'shoppingItemsDomainsType' => 'manual',
					'domainSLD' => $domainData['SLD'],
					'domainTLD' => $domainData['TLD']
				);
				$domains[] = $data;
			}

			
			foreach ($purchase->getPurchases() as $subPurchase) {
				$subPlan = $this->_store->getPlan($subPurchase->getPlanId());
				if ($subPlan->productType == BillingPlan::TYPE_DOMAIN) {
					$data = array(
						'shoppingItemsDomainsRelID' => $subPurchase->getId(),
						'shoppingItemsDomainsType'	=> $subPurchase->getParameter('type'),
						'domainShoppingItemID'		=> $subPurchase->getId()
					);
					$domains[] = $data;
					if ($primaryDomainId === false) {
						$primaryDomainId = $subPurchase->getId();
					}
				}
			}
			
			if ($domains) {
				$itemData['domains'] = $domains;
				$itemData['shoppingItemPrimaryDomainID'] = $primaryDomainId;
			}
			
		}
		
		if ($plan->productType == BillingPlan::TYPE_SSL_CERTIFICATE) {
			$itemData['certificates'] = array($this->prepareCertificateData($purchase));
		}
		
		return $itemData;
		
	}
	
	private function prepareDomainData(Purchase $purchase, BillingStore $store, BillingPlan $plan, BillingPrice $price, &$inputParams) {
		
		$cycleId = $purchase->getCycleId();
		
		$itemData = $this->prepareItemData($purchase, $price, $plan->productType);
		$inputParams = array_merge($inputParams,(array)$purchase->getParameter('customQuestionData'));
		if ($addons = $this->prepareAddonData($purchase, $plan, $store, $cycleId, $inputParams)) {
			$itemData['children'] = $addons;
		}
		
		$domainData = $purchase->getParameter('domainData');
		$SLD = $domainData['SLD'];
		$TLD = $domainData['TLD'];
		$domainData = array(
			'shoppingItemDomainType' => $purchase->getParameter('type'),
			'shoppingItemSLD' => $SLD,
			'shoppingItemTLD' => $TLD,
			'shoppingItemDomainLanguage' => false
		);
		$itemData = array_merge($itemData, $domainData);
		
		if (!isset($inputParams['extAttrib'])) {
			$inputParams['extAttrib'] = array();
		}
		$domainName = $SLD . '.' . $TLD;
		$inputParams['extAttrib'][$domainName] = $purchase->getParameter('data');
		
		return $itemData;
		
	}
	
	public function prepareCertificateData(PurchaseContainer $container) {
		$data = $container->getParameter('data');
		$dn = $data['dn'];
		return array(
			'dn' => $dn,
			'csr' => $data['csr'],
			'pkey' => $data['pkey'],
			'webServerType' => $data['webServerType']
		);
	}
	
	private function prepareItemData(PurchaseContainer $container, BillingPrice $price, $planType, $parentId = null) {
		$variantId = $price->productVariantID;
		$cycleId = $container->getCycleId();
		$useTransferFee = $planType == BillingPlan::TYPE_DOMAIN && $container->getParameter('type') == BillingDomainPlan::PURCHASE_TYPE_TRANSFER ? true : false;
		return array(
			'shoppingItemID'			=> $container->getId(),
			'parentShoppingItemID'		=> $parentId,
			'productID'					=> $container instanceof Purchase ? $container->getPlanId() : $container->getAddonId(),
			'productVariantID'			=> $variantId,
			'cycleID'					=> $cycleId,
			'shoppingItemPrice' 		=> $useTransferFee ? $price->getTransferFee(false, false) : $price->getCycleFee(false, false),
			'shoppingItemSetupPrice'	=> $price->getSetupFee(),
			'appliedCouponID'			=> $container->hasCoupon() ? $container->getCoupon()->getId() : null
		);
	}
	
	private function prepareAddonData(Purchase $purchase, BillingPlan $plan, BillingStore $store, $cycleId, &$inputParams) {
		$addons = array();
		if ($purchase->hasAddons()) {
			$billingAddons = $plan->getAddons($this->_store->getId(), $cycleId);
			foreach ($purchase->getAddons() as $addon) {
				$billingAddon = isset($billingAddons[$addon->getAddonId()]) ? $billingAddons[$addon->getAddonId()] : null;
				if (!$billingAddon || !$billingAddon->productIsAddon) {
					continue;
				}
				$data = array(
					'shoppingItemID'			=> $addon->getId(),
					'productID'					=> $billingAddon->getId(),
					'productVariantID'			=> $billingAddon->getPrice()->productVariantID,
					'shoppingItemPrice'			=> $billingAddon->getPrice()->getCycleFee(false, false),
					'shoppingItemSetupPrice'	=> $billingAddon->getPrice()->getSetupFee(),
					'appliedCouponID'			=> $addon->hasCoupon() ? $addon->getCoupon()->getId() : null
				);
				$addons[] = $data;
			}
		}
		return $addons;
	}

    private function _loginJustAddedCustomer($customerData) {
        try {
            ResourceLocator::getInstance()->billingContactService->login($customerData['contactUsername'], $customerData['contactPassword']);
            $this->getUser()->getAttributeHolder()->remove('customerData');
        } catch (StoreException $exception) {
            $this->logMessage('Unable to login as just created customer [login=' . $customerData['contactUsername'] . ']; ' . get_class($exception) . ' message: ' . $exception->getMessage(), 'err');
        }
    }
}