<?php

// TODO: metode de import de pe entitate de oferta - pt operatiune (insert/select) - testat metode de populare...

// TODO: daca operatiunea este refund - nu am voie sa am serviceFee procentual

namespace App\OfferProfileRules;

class Fields
{

	/**
	 * The current operation (eg. issue, refund).
	 * @var String
	 */
	public $operation = 'issue';

	/**
	 * Reissue ticket.
	 * @var Boolean
	 */
	public $reissue;

	/**
	 * The external reservations system id.
	 * @var Int
	 */
	public $idExtResSystem;

	/**
	 * The service code on the offer pivot.
	 * @var String
	 */
	public $serviceCode;

	/**
	 * The current location.
	 * @var String
	 */
	public $offerLocation;

	/**
	 * The start date (check in date) stored at offer level.
	 * @var String - date in ISO format
	 */
	public $offerStartDate;

	/**
	 * The owner corporate of the order which contains the current service.
	 * @var Int
	 */
	public $idOwnerCorporate;

	/**
	 * The owner customer of the order which contains the current service.
	 * @var Int
	 */
	public $idFirstCustomer;

	/**
	 * The passenger type
	 * @var String
	 */
	public $passengerType;

	/**
	 * The service responsible user.
	 * @var Int
	 */
	public $idServiceUser;

	/**
	 * The offer supplier id.
	 * @var Int
	 */
	public $idSupplier;

	/**
	 * Offer supplier category
	 * @var string
	 */
	public $supplierCategory;

	/**
	 * The book office for the imported service.
	 * @var String
	 */
	public $importedServiceBookOffice;

	/**
	 * The issue office for the imported service.
	 * @var String
	 */
	public $importedServiceIssueOffice;

	/**
	 * The offer departure country code.
	 * @var String
	 */
	public $offerDepartureCountryCode;

	/**
	 * The offer departure city id.
	 * @var Int
	 */
	public $offerDepartureCityId;

	/**
	 * The offer departure station code.
	 * @var String
	 */
	public $offerDepartureStationCode;

	/**
	 * The offer destination country code.
	 * @var String
	 */
	public $offerDestinationCountryCode;

	/**
	 * The offer destination city id.
	 * @var Int
	 */
	public $offerDestinationCityId;

	/**
	 * The offer destination station code.
	 * @var String
	 */
	public $offerDestinationStationCode;

	/**
	 * Offer attributes - category.
	 * @var String
	 */
	public $offerCategory;

	/**
	 * Offer attributes - product type.
	 * @var String
	 */
	public $offerProductType;

	/**
	 * Offer attributes - supplier product.
	 * @var String
	 */
	public $offerIdSupplierProduct;

	/**
	 * Offer attributes - product multiplier.
	 * @var array[String]
	 */
	public $offerProductMultiplier;

	/**
	 * The offer form of payment (cash, cc, etc)
	 * @var String
	 */
	public $offerFormOfPayment;

	/**
	 * The offer total currency.
	 * @var String
	 */
	public $offerTotalCurrency;

	/**
	 * The MICE project id.
	 * @var Int
	 */
	public $idMiceProject;


	/**
	 * service price on the offer
	 * @var float
	 */
	public $servicePriceValue;
	public $servicePriceCurrency;

	/**
	 * total price on the offer
	 * @var float
	 */
	public $totalPriceValue;
	public $totalPriceCurrency;

	/**
	 * currency date on the offer
	 * @var  String - date in ISO format
	 */
	public $currencyDate;

	/**
	 * the service class code
	 * @var string
	 */
	public $serviceClassCode;

	/**
	 * the service class name
	 * @var string
	 */
	public $serviceClassName;

	/**
	 * the fare basis - filled in from remarks
	 * @var array
	 */
	public $fareBasis = [];

	/**
	 * the flight type
	 * @var string
	 */
	public $flightType;

	/**
	 * the processed remarks
	 * @var array
	 */
	public $serviceRemarks;

	/**
	 * the global area from offer destination country and offer departure country
	 * @var string
	 */
	public $globalArea;

	/**
	 * the global destination from offer destination country and offer departure country
	 * @var string
	 */
	public $globalDestination;

	/**
	 * set the service class code, service class name and flight type from the itinerary
	 * these fields are set only if they are different than null
	 * it is important to try to set these fields from itinerary after you check if they are set manually
	 * @param \App\Itinerary $itinerary
	 */
	public function setFromItinerary(\App\Itinerary $itinerary)
	{
		if (!$itinerary->getSegments()) {
			return;
		}

		if ($this->serviceClassCode===null) {
			$classCode = $itinerary->getUniqueServiceClassCodes()[0];
			if ($classCode) {
				$this->serviceClassCode = $classCode;
			}
		}

		if ($this->serviceClassName===null) {
			$className = $itinerary->getUniqueServiceClassNames()[0];
			if ($className) {
				$this->serviceClassName = $className;
			}
		}
		if ($this->flightType===null) {
			$itineraryAnalyser = new \App\Utils\Itinerary\ItineraryAnalyser($itinerary);
			$itineraryAnalyser->analyse();
			if ($itineraryAnalyser->getType()) {
				$this->flightType = $itineraryAnalyser->getType();
			}
		}

		// fill in the fare basis details
		$this->fareBasis = [];
		foreach($itinerary->getSegments() as $segment) {
			if ($segment->getFareBasis()) {
				$this->fareBasis[] = $segment->getFareBasis();
			}
		}

	}



	/**
	 * Populates the internal fields starting from offer details (select operation) - it also populates the service and order fields.
	 * @param \Entity\Offer $offer
	 * @throws \Exception
	 */
	public function populateFromOfferEntitySelect(\Entity\Offer $offer)
	{
		// check the input operation
		if ($offer->getOperation()!='select') {
			throw new \Exception('The offer entity operation must be `select`.');
		}

		// POPULATE OFFER FIELDS //////////////////////////////////////////////////////////////////

		// set the main fields
		$this->serviceCode = $offer->serviceCode;
		$this->offerLocation = $offer->locationCode;
		$this->offerStartDate = $offer->startDate;
 		$this->idSupplier = $offer->idSupplier;
 		$this->supplierCategory = $offer->supplier->category;

 		// set the departure and the destination
		if ($offer->departureCountryCode) {
 			$this->offerDepartureCountryCode = $offer->departureCountryCode;
		}
		if ($offer->departureCityId) {
			$this->offerDepartureCityId = $offer->departureCityId;
		}
		if ($offer->departureStationCode) {
			$this->offerDepartureStationCode = $offer->departureStationCode;
		}
		if ($offer->destinationCountryCode) {
			$this->offerDestinationCountryCode = $offer->destinationCountryCode;
		}
		if ($offer->destinationCityId) {
			$this->offerDestinationCityId = $offer->destinationCityId;
		}
		if ($offer->destinationStationCode) {
			$this->offerDestinationStationCode = $offer->destinationStationCode;
		}

		// global area
		$departureZone = ($offer->departureCountryCode ? \Entity\Country::select($offer->departureCountryCode)->zone : '');
		$destinationZone = ($offer->destinationCountryCode ? \Entity\Country::select($offer->destinationCountryCode)->zone : '');
		$this->globalArea = \App\Utils\Place::getCountryZoneFromZoneList($departureZone, $destinationZone);

		// global destination
		$this->globalDestination = ($offer->departureCountryCode && $offer->departureCountryCode==$offer->destinationCountryCode?'domestic':'international');

		// supplier product
		if ($offer->idSupplierProduct) {
			$this->offerIdSupplierProduct = $offer->idSupplierProduct;
		}

		// set extra offer stuff
		if ($offer->formOfPayment) {
			$this->offerFormOfPayment = $offer->formOfPayment;
		}

		// set the itinerary
		$itineraryObj = $offer->itinerary;
		if ($itineraryObj) {
			$this->setFromItinerary($itineraryObj);
		}

		$this->currencyDate  		= $offer->currencyDate;

		$this->servicePriceValue 	= $offer->supplierWorkValue + $offer->supplierWorkVat + $offer->commissionWorkValue + $offer->commissionWorkVat;
		$this->servicePriceCurrency = $offer->totalCurrency;

		$this->totalPriceValue 		= $this->servicePriceValue + $offer->taxWorkValue + $offer->taxWorkVat;
		$this->totalPriceCurrency	= $offer->totalCurrency;

		$this->offerTotalCurrency = $offer->totalCurrency;

		// populates the service stuff
		$this->populateFromServiceEntitySelect($offer->service);
	}

	/**
	 * Populates the internal fields starting from service details (select operation) - it also populates the order fields.
	 * @param \Entity\Service $service
	 * @throws \Exception
	 */
	public function populateFromServiceEntitySelect(\Entity\Service $service)
	{
		// check the input operation
		if ($service->getOperation()!='select') {
			throw new \Exception('The service entity operation must be `select`.');
		}

		// POPULATE SERVICE FIELDS ////////////////////////////////////////////////////////////////

		// external system and importedServiceBookOffice + issueOffice
		if ($service->idImportedService) {
			$importedService = $service->importedService;

			$this->idExtResSystem = $importedService->idSystem;
			if ($importedService->idBookOfficeSystem) {
				$this->importedServiceBookOffice = $importedService->idBookOfficeSystem;
			}
			if ($importedService->idIssueOfficeSystem) {
				$this->importedServiceIssueOffice = $importedService->idIssueOfficeSystem;
			}
			if ($importedService->object and $importedService->object->chosenOffer and $importedService->object->chosenOffer->totalCurrency) {
				$this->offerTotalCurrency = $importedService->object->chosenOffer->totalCurrency;
			}
			// reissue
			$this->reissue = (Boolean)$importedService->object->idReissuedService;

		}

		// populate customer details (id+type)
		if ($service->idFirstCustomer) {
			$this->idFirstCustomer = $service->idFirstCustomer;
			$this->passengerType = \Entity\Customer::select($this->idFirstCustomer)->typeCode;
		}

		// ATTACH SERVICE ATTRIBUTES ////////////////////////////////////////////////////////////// TODO: move this at offer level
		if ($service->categoryCode) {
			$this->offerCategory = $service->categoryCode;
		}
		if ($service->productTypeCode) {
			$this->offerProductType = $service->productTypeCode;
		}
		if ($service->multiplierCode and is_array($service->multiplierCode)) {
			$this->offerProductMultiplier = array_keys($service->multiplierCode);
		}

		// populate service remarks
		if ($service->processedRemarks) {
			$this->serviceRemarks = $service->processedRemarks;
		}
		if ($service->idUser) {
			$this->idServiceUser = $service->idUser;
		}

		// populates the order stuff
		$this->populateFromOrderEntitySelect($service->order);

	}

	/**
	 * Populates the internal fields starting from order details (select operation).
	 * @param \Entity\Order $order
	 * @throws \Exception
	 */
	public function populateFromOrderEntitySelect(\Entity\Order $order)
	{
		// check the input operation
		if ($order->getOperation()!='select') {
			throw new \Exception('The order entity operation must be `select`.');
		}

		// POPULATE SERVICE FIELDS ////////////////////////////////////////////////////////////////

		// corporate/customer owner
		if ($order->idCorporateOwner) {
			$this->idOwnerCorporate = $order->idCorporateOwner;
		}

		if ($order->idMiceProject) {
			$this->idMiceProject = $order->idMiceProject;
		}
	}


	/**
	 * Populates the internal fields starting from offer details (insert operation).
	 * @param \Entity\Offer $offer
	 * @throws \Exception
	 */
	public function populateFromOfferEntityInsert(\Entity\Offer $offer)
	{
		// check the input operation
		if ($offer->getOperation()!='insert') {
			throw new \Exception('The offer entity operation must be `insert`.');
		}

		// POPULATE OFFER FIELDS //////////////////////////////////////////////////////////////////
		$fields = $offer->getFields();

		// set the main fields
		$this->serviceCode = $fields['serviceCode'];
		$this->offerLocation = $fields['location'];
		if ($fields['startDatetime']) { // check if the offer startDatetime is filled before populate the offer start date
			$this->offerStartDate = $fields['startDatetime']->formatDateIso();
		}
 		$this->idSupplier = $fields['idSupplier'];
 		$this->supplierCategory = \Entity\Supplier::select($fields['idSupplier'])->category;

 		// set the departure and the destination
		if ($fields['departureCountryCode']) {
 			$this->offerDepartureCountryCode = $fields['departureCountryCode'];
		}
		if ($fields['departureCityId']) {
			$this->offerDepartureCityId = $fields['departureCityId'];
		}
		if ($fields['departureStationCode']) {
			$this->offerDepartureStationCode = $fields['departureStationCode'];
		}
		if ($fields['destinationCountryCode']) {
 			$this->offerDestinationCountryCode = $fields['destinationCountryCode'];
		}
		if ($fields['destinationCityId']) {
			$this->offerDestinationCityId = $fields['destinationCityId'];
		}
		if ($fields['destinationStationCode']) {
			$this->offerDestinationStationCode = $fields['destinationStationCode'];
		}

		// global area
		$departureZone = ($fields['departureCountryCode'] ? \Entity\Country::select($fields['departureCountryCode'])->zone : '');
		$destinationZone = ($fields['destinationCountryCode'] ? \Entity\Country::select($fields['destinationCountryCode'])->zone : '');
		$this->globalArea = \App\Utils\Place::getCountryZoneFromZoneList($departureZone, $destinationZone);

		// global destination
		$this->globalDestination = ($fields['departureCountryCode'] && $fields['departureCountryCode']==$fields['destinationCountryCode']?'domestic':'international');

		// supplier product
		if ($fields['idSupplierProduct']) {
			$this->offerIdSupplierProduct = $fields['idSupplierProduct'];
		}

		// offer total currency
		if ($fields['totalCurrency']) {
			$this->offerTotalCurrency = $fields['totalCurrency'];
		}

		// set extra offer stuff
		if ($fields['formOfPayment']) {
			$this->offerFormOfPayment = $fields['formOfPayment'];
		}

		// set the itinerary
		if ($fields['itinerary']) {
			$this->setFromItinerary($fields['itinerary']);
		}

		$this->currencyDate  		= $fields['currencyDate'];

		if ($fields['totalCurrency']) {
			$this->offerTotalCurrency = $fields['totalCurrency'];
		}

		$this->populateFromOfferItemEntityInsert($offer);

	}

	/**
	 * Populates the internal fields starting from offer item
	 * @param \Entity\Offer
	 */
	private function populateFromOfferItemEntityInsert(\Entity\Offer $offer)
	{
		$offerFields = $offer->getFields();

		$commissionable = $offerFields['commissionable'];

		$offerItemsArr 	= $offer->getField('offerItems');
		$offerItemEnt 	= $offerItemsArr[0];

		$offerItemFields = $offerItemEnt->getFields();


		$this->servicePriceCurrency	= $offerItemFields['supplierInitialCurrency'];
		if ($commissionable) {
			$this->servicePriceValue = \App\CurrencyExchange\Rates::getInstance($this->currencyDate)->convert($offerItemFields['supplierInitialValue'], $offerItemFields['supplierInitialCurrency'], $this->servicePriceCurrency) * $offerItemFields['quantity'];
		}
		else {
			$this->servicePriceValue = (\App\CurrencyExchange\Rates::getInstance($this->currencyDate)->convert($offerItemFields['supplierInitialValue'], $offerItemFields['supplierInitialCurrency'], $this->servicePriceCurrency)  * $offerItemFields['quantity'] )
				+ ( \App\CurrencyExchange\Rates::getInstance($this->currencyDate)->convert($offerItemFields['commissionInitialValue'], $offerItemFields['commissionInitialCurrency'], $this->servicePriceCurrency) * $offerItemFields['quantity']);
		}

		$this->totalPriceCurrency= $offerFields['totalCurrency'];
		$this->totalPriceValue = \App\CurrencyExchange\Rates::getInstance($this->currencyDate)->convert($this->servicePriceValue, $this->servicePriceCurrency, $this->totalPriceCurrency) +
			(\App\CurrencyExchange\Rates::getInstance($this->currencyDate)->convert($offerItemFields['taxInitialValue'], $offerItemFields['taxInitialCurrency'], $this->totalPriceCurrency) * $offerItemFields['quantity']);
	}

	/**
	 * Populates the internal fields starting from service details (insert operation).
	 * @param \Entity\Service $service
	 * @throws \Exception
	 */
	public function populateFromServiceEntityInsert(\Entity\Service $service)
	{

		// check the input operation
		if ($service->getOperation()!='insert') {
			throw new \Exception('The service entity operation must be `insert`.');
		}

		// POPULATE SERVICE FIELDS ////////////////////////////////////////////////////////////////

		$fields = $service->getFields();

		// external system and importedServiceBookOffice + issueOffice
		if ($fields['idImportedService']) {

			$importedService = \Entity\ImportedService::select($fields['idImportedService']);

			$this->idExtResSystem = $importedService->idSystem;
			if ($importedService->idBookOfficeSystem) {
				$this->importedServiceBookOffice = $importedService->idBookOfficeSystem;
			}
			if ($importedService->idIssueOfficeSystem) {
				$this->importedServiceIssueOffice = $importedService->idIssueOfficeSystem;
			}
			if ($importedService->object->chosenOffer and $importedService->object->chosenOffer->totalCurrency) {
				$this->offerTotalCurrency = $importedService->object->chosenOffer->totalCurrency;
			}
			// reissue
			$this->reissue = (Boolean)$importedService->object->idReissuedService;
		}

		if ($fields['idCustomers']) {
			$this->idFirstCustomer = reset($fields['idCustomers']);
			$this->passengerType = \Entity\Customer::select($this->idFirstCustomer)->typeCode;
		}

		// ATTACH SERVICE ATTRIBUTES ////////////////////////////////////////////////////////////// TODO: move this at offer level
		if ($fields['category']) {
			$this->offerCategory = $fields['category'];
		}
		if ($fields['productType']) {
			$this->offerProductType = $fields['productType'];
		}
		if (is_array($fields['multiplier']) and $fields['multiplier']) {
			$this->offerProductMultiplier = array_keys($fields['multiplier']);
		}

		// attach service remarks
		if ($fields['processedRemarks']) {
			$this->serviceRemarks = $fields['processedRemarks'];
		}

		if ($fields['idUser']) {
			$this->idServiceUser = $fields['idUser'];
		}
	}
}
