<?php

class SummaryAction extends CartAction {
	
	const OPERATION_ADD_DOMAIN = 'add-domain';
	const OPERATION_ADD_ADDONS = 'add-addons';
	const OPERATION_REMOVE_PURCHASE = 'remove-purchase';
	const OPERATION_REMOVE_OWN_DOMAIN = 'remove-own-domain';
	const OPERATION_REMOVE_ADDON = 'remove-addon';
	const OPERATION_APPLY_COUPON = 'apply-coupon';
	const OPERATION_CONTINUE_ORDER = 'continue-order';
	
	public function execute($request) {
		
		sfContext::getInstance()->getConfiguration()->loadHelpers('I18N');
		
		$cartItems = $this->_cart->getItems();
		
		if ($request->isMethod('post')) {
			
			$cartItemId = $request->getParameter('cartItemId');
			$purchaseId = $request->getParameter('purchaseId');
			$addonId = $request->getParameter('addonId');
			$operation = $request->getParameter('operation');
			
			switch ($operation) {
				case self::OPERATION_ADD_ADDONS:
					$cartItem = ResourceLocator::getInstance()->cart->getItem($cartItemId);
					ResourceLocator::getInstance()->cart->setCurrentItem($cartItem);
					$router = new Router();
					$router->init(
						array(
							new RouterPage('select-addons'),
							new RouterPage('summary')
						),
						new RouterPage('summary')
					);
					ResourceLocator::getInstance()->routersStack->push($router);
					$router->next();
					break;
				case self::OPERATION_ADD_DOMAIN:
					$cartItem = ResourceLocator::getInstance()->cart->getItem($cartItemId);
					$cartItem->setMasterPurchase($purchaseId);
					$this->_cart->setCurrentItem($cartItem);
					$router = new Router();
					$router->init(
						array(
							new RouterPage('select-domain'),
							new RouterPage('register-domain'),
							new RouterPage('summary')
						),
						new RouterPage('summary')
					);
					ResourceLocator::getInstance()->routersStack->push($router);
					$router->next();
					break;
				case self::OPERATION_REMOVE_PURCHASE:
					$this->_cart->removePurchase($purchaseId);
					break;
				case self::OPERATION_REMOVE_OWN_DOMAIN:
					$purchase = ResourceLocator::getInstance()->cart->getPurchase($purchaseId);
					$purchase->removeParameter('domainData');
					break;
				case self::OPERATION_REMOVE_ADDON:
					ResourceLocator::getInstance()->cart->getPurchase($purchaseId)->removeAddon($addonId);
					break;
				case self::OPERATION_APPLY_COUPON:
					$code = $request->getParameter('coupon');
					$itemIds = array();
					$purchases = $this->_cart->getPurchases();
					foreach ($purchases as $purchase) {
						if (!isset($itemIds[$purchase->getPlanId()])) {
							$itemIds[$purchase->getPlanId()] = array();
						}
						$itemIds[$purchase->getPlanId()][] = $purchase;
						if ($purchase->hasCouponByCode($code)) {
							$purchase->unsetCoupon();
						}
						foreach ($purchase->getAddons() as $addon) {
							if (!isset($itemIds[$addon->getAddonId()])) {
								$itemIds[$addon->getAddonId()] = array();
							}
							$itemIds[$addon->getAddonId()][] = $addon;
							if ($addon->hasCouponByCode($code)) {
								$addon->unsetCoupon();
							}
						}
					}
					$targetIds = array_keys($itemIds);
					try {
						$ids = array();
						$coupon = ResourceLocator::getInstance()->billingCouponService->applyCoupon(
							$this->_store->getId(),
							$targetIds,
							$code,
							$ids
						);
						$names = array();
						foreach ($ids as $id) {
							if (isset($itemIds[$id])) {
								foreach ($itemIds[$id] as $item) {
									if ($item->setCoupon($coupon)) {
										$names[] = $item->getName();
										if ($coupon->couponApplyNumber) {
											break;
										}
									}
								}
							}
						}
						if (!$names) {
							throw new StoreException();
						}
						sfContext::getInstance()->getUser()->setAttribute('couponSuccessMessage', 'TRANS_COUPON_VALID');
						$output = implode(', ', $names);
						sfContext::getInstance()->getUser()->setAttribute('couponSuccessNames', $output);
					} catch (BillingObjectException $exception) {
						sfContext::getInstance()->getUser()->setAttribute('errorMessage', 'TRANS_COUPON_INVALID');
					}
					break;
				case self::OPERATION_CONTINUE_ORDER:
					$noOneDomainNames = array();
					$noOneAddonGroupNames = array();
					$noOneAddonNames = array();
					$plans = $this->_store->getPlans();
					// check plans, that must have domains and addons
					foreach (ResourceLocator::getInstance()->cart->getPurchases() as $purchase) {
						if (!$plan = $plans[$purchase->getPlanId()]) {
							throw new StoreException('Can not retrieve plan [' . $purchase->getPlanId() . ']');
						}
						if ($plan->mustHaveDomains()) {
							if (!$purchase->hasParameter('domainData')) {
								$result = false;
								foreach ($purchase->getPurchases() as $subPurchase) {
									$subPlan = $plans[$subPurchase->getPlanId()];
									if ($subPlan instanceof BillingDomainPlan) {
										$result = true;
										break;
									}
								}
								if (!$result) {
									$noOneDomainNames[] = $purchase->getName();
								}
							}
						}
						foreach ($plan->getAddonGroups($this->_store->getId(), $purchase->getCycleId()) as $addonGroup) {
							if (!$addonGroup->productAddonGroupNoneChoice) {
								$result = false;
								foreach ($addonGroup->getAddons() as $addon) {
									if ($purchase->hasAddonByAddonId($addon->getId())) {
										$result = true;
										break;
									}
								}
								if (!$result) {
									$noOneAddonGroupNames[] = $addonGroup->productAddonGroupName;
								}
							}
						}
						if ($plan->mustHaveAddons()) {
							if (!$result = $purchase->hasAddons()) {
								$noOneAddonNames[] = $purchase->getName();
							}
						}
					}
					if ($noOneDomainNames) {
						sfContext::getInstance()->getUser()->setAttribute('errorMessage', __('TRANS_FOLLOWING_PLANS_MUST_HAVE_DOMAINS', array('%NAMES%' => implode(', ', array_unique($noOneDomainNames)))));
					} else if ($noOneAddonGroupNames) {
						sfContext::getInstance()->getUser()->setAttribute('errorMessage', __('TRANS_FOLLOWING_ADDON_GROUPS_MUST_HAVE_ADDONS', array('%NAMES%' => implode(', ', array_unique($noOneAddonGroupNames)))));
					} else if ($noOneAddonNames) {
						sfContext::getInstance()->getUser()->setAttribute('errorMessage', __('TRANS_FOLLOWING_PLANS_MUST_HAVE_ADDONS', array('%NAMES%' => implode(', ', array_unique($noOneAddonNames)))));
					} else {
						$this->_router->next();
					}
					break;
			}
			
			$this->_router->refresh();
			
		}
		
		$amount = 0;
		$totalAmount = 0;
		$minimalCycle = null;
		
		$cartItemsData = array();
		foreach ($cartItems as $cartItemId => $cartItem) {
			$cartItemData = array();
			
			foreach ($cartItem->getPurchases() as $purchase) {
				$subPurchases = $purchase->getPurchases(true);
				$cartItemData[$purchase->getId()] = $this->preparePurchaseData($purchase, $subPurchases, $amount, $totalAmount, $minimalCycle);
				$addons = array();
				foreach ($purchase->getAddons(true) as $addon) {
					$addons[] = $this->prepareAddonData($addon, $amount, $totalAmount, $minimalCycle);
				}
				$cartItemData[$purchase->getId()]['addons'] = $addons;
			}
			
			if ($cartItemData) {
				$cartItemsData[$cartItemId] = $cartItemData;
			}
			
		}
		
		$this->amount = $amount;
		$this->totalAmount = $totalAmount;
		$this->minimalCycle = $minimalCycle;
		
		$this->cartItemsData = $cartItemsData;
		
		$customer = sfContext::getInstance()->getUser()->getAttribute('customer');
		$customerData = sfContext::getInstance()->getUser()->getAttribute('customerData');
		if (!$customer && !$customerData && ($defaultTaxZoneId = isset($this->_store->defaultTaxZoneID) ? $this->_store->defaultTaxZoneID : false)) {
			$this->taxZone = ResourceLocator::getInstance()->billingTaxZoneService->getById($defaultTaxZoneId);
		}
		
		if ($this->couponSuccessMessage = sfContext::getInstance()->getUser()->getAttribute('couponSuccessMessage')) {
			$this->couponSuccessNames = sfContext::getInstance()->getUser()->getAttribute('couponSuccessNames');
			sfContext::getInstance()->getUser()->setAttribute('couponSuccessMessage', null);
			sfContext::getInstance()->getUser()->setAttribute('couponSuccessNames', null);
		}
		
		if ($this->errorMessage = sfContext::getInstance()->getUser()->getAttribute('errorMessage')) {
			sfContext::getInstance()->getUser()->setAttribute('errorMessage', null);
		}
		
	}
	
	private function preparePurchaseData($purchase, $subPurchases = array(), &$amount, &$totalAmount, &$minimalCycle) {
		$subData = array();
		
		$plan = ResourceLocator::getInstance()->billingPlanService->getById(
			$purchase->getPlanId(),
			$this->_store->getId(),
			$purchase->hasCoupon() ? $purchase->getCoupon()->getId() : false
		);
		
		if ($plan->productType != BillingPlan::TYPE_DOMAIN && $purchase->hasParameter('domainData')) {
			$fakeId = ResourceLocator::getInstance()->cart->generateFakeId();
			$domainData = $purchase->getParameter('domainData');
			$subData[$fakeId] = array(
				'id' => $fakeId,
				'type' => __('TRANS_YOUR_OWN_DOMAIN'),
				'name' => $domainData['name'],
				'price' => null,
				'cycle' => null,
				'hasAddAddonAbility' => false,
				'hasAddDomainAbility' => false,
				'fake' => true,
				'purchases' => array()
			);
		}
		
		foreach ($subPurchases as $subPurchase) {
			$subData[$subPurchase->getId()] = $this->preparePurchaseData($subPurchase, array(), $amount, $totalAmount, $minimalCycle);
		}
		
		$useTransferFee = $plan instanceof BillingDomainPlan && $purchase->getParameter('type') == BillingDomainPlan::PURCHASE_TYPE_TRANSFER ? true : false;
		
		$price = $plan->getPriceById($purchase->getPriceId());
		$cycle = $plan->getCycle($price->cycleID);
		if (!$minimalCycle || $minimalCycle->getLength() < $cycle->getLength()) {
			$minimalCycle = $cycle;
		}
		$amount += $price->getTotalFee(true, false, $useTransferFee);
		$totalAmount += $price->getTotalFee(true, true, $useTransferFee);
		
		$hasAddAddonAbility = $plan->mayHaveAddons() && $plan->hasAddAddonAvailability($cycle->cycleID);
		
		$hasAddDomainAbility = false;
		if ($plan->mayHaveDomains()) {
			if ($this->_store->hasAbilityToUseOwnDomain()) {
				$hasAddDomainAbility = true;
			} else {
				$domainPlan = $plan instanceof BillingDomainPlan ? $plan : $this->_store->getDefaultDomainPlan();
				if ($domainPlan && $this->_store->hasAbilityToPurchaseDomainPlan($domainPlan)) {
					$hasAddDomainAbility = true;
				}
			}
		}
		
		$data = array(
			'id' => $purchase->getId(),
			'type' => __('TRANS_PRODUCT_TYPE_NAME_' . $plan->productType),
			'name' => $purchase->getName(),
			'price' => $price,
			'cycle' => $cycle,
			'hasAddAddonAbility' => $hasAddAddonAbility,
			'hasAddDomainAbility' => $hasAddDomainAbility,
			'useTransferFee' => $useTransferFee,
			'fake' => false,
			'purchases' => $subData
		);
		
		return $data;
	}
	
	private function prepareAddonData($addon, &$amount, &$totalAmount, &$minimalCycle) {
		
		$billingAddon = ResourceLocator::getInstance()->billingAddonService->getById(
			$addon->getAddonId(),
			$addon->getPlanId(),
			$this->_store->getId(),
			$addon->getCycleId(),
			$addon->hasCoupon() ? $addon->getCoupon()->getId() : false
		);
		
		$price = $billingAddon->getPrice();
		$cycle = $billingAddon->getCycle($price->cycleID);
		if (!$minimalCycle || $minimalCycle->getLength() < $cycle->getLength()) {
			$minimalCycle = $cycle;
		}
		$amount += $price->getTotalFee(true, false);
		$totalAmount += $price->getTotalFee();
		
		return array(
			'id' => $addon->getId(),
			'name' => $billingAddon->productName,
			'price' => $price,
			'cycle' => $cycle
		);
		
	}
	
}