<?php
namespace App\GenDocument\PivotCalendarEvent;

class ImportedService
{
	/**
	 * Stores the calendar object
	 * @var \App\Utils\Calendar\Calendar
	 */
	protected $calendarObject = NULL;

	/**
	 * Stores the imported service entity
	 * @var \Entity\ImportedService
	 */
	protected $importedServiceEntity = NULL;

	/**
	 * The default construct of the class
	 * @param \App\Utils\Calendar\Calendar $calendarObject
	 * @param \Entity\ImportedService $importedServiceEntity
	 */
	public function __construct(\App\Utils\Calendar\Calendar $calendarObject, \Entity\ImportedService $importedServiceEntity)
	{
		$this->calendarObject = 			$calendarObject;
		$this->importedServiceEntity = 		$importedServiceEntity;
	}


	/**
	 * Populate the calendar with events
	 */
	public function populate()
	{
		$msgs = new \App\MessagesCollector();

		// get imported service object
		$importedServiceObject = $this->importedServiceEntity->object;

		// get chosen offer
		$chosenOfferObject = $importedServiceObject->chosenOffer;

		if (!$chosenOfferObject) {
			throw new \App\MessagesException($msgs->addWarning(sprintf("The imported service(%s) doesn't have offer associated.", $this->importedServiceEntity->getId())));
		}

		// get itinerary
		$itineraryObject = $chosenOfferObject->itinerary;

		if ($itineraryObject) {
			foreach ($itineraryObject->segments as $segmentIndex => $segmentObj) {
				// create events
				$eventObject = new \App\Utils\Calendar\Event();

				$this->populateEventFromItinerarySegment($segmentObj, $eventObject);
				////////// ADD REMINDER TO FIRST EVENT //////////////////////////////////////////////////////
				if ($segmentIndex === 0) {

					$reminderObject = new \App\Utils\Calendar\Reminder();
					$reminderObject->setTrigger(new \Engine\DateInterval('P1D'));
					$reminderObject->setAction('DISPLAY');

					$arrivalPlaceObject = $segmentObj->arrivalPlace;
					$reminderObject->setDescription($this->getSummary($arrivalPlaceObject));

					$eventObject->addReminder($reminderObject);
				}

				$this->calendarObject->addEvent($eventObject);

			}
		}

		if (!$this->calendarObject->getNumberOfEvents()) {

			$eventObject = new \App\Utils\Calendar\Event();
			$this->populateEventFromService($importedServiceObject, $eventObject);
			$this->calendarObject->addEvent($eventObject);
		}
	}

	/**
	 * Populate the event object from imported service
	 * @param \App\ImportedOrder\Service $importedServiceObject
	 * @param \App\Utils\Calendar\Event $eventObject
	 */
	private function populateEventFromService(\App\ImportedOrder\Service $importedServiceObject, \App\Utils\Calendar\Event $eventObject)
	{
		// get choosen offer
		$chosenOfferObject = $importedServiceObject->chosenOffer;

		// get departure datetime
		$departureDateTimeObject = $chosenOfferObject->departureDateTime;


		////////// POPULATE EVENT UNIQUE ID ////////////////////////////////////////////////////////
		$eventObject->setUid(sprintf("%sZ-%s-%s",
			\Engine\DateTime::create()->format('Ymd\THis'),
			\Engine\RandomGenerator::randomString(mt_rand(5, 10)),
			\Engine\RandomGenerator::randomString(mt_rand(10, 15))
		));

		//////// POPULATE EVENT SUMMARY ////////////////////////////////////////////////////////////
		$destinationPlaceObject = $chosenOfferObject->destinationPlace;
		$eventObject->setSummary($this->getSummary($destinationPlaceObject));

		///////////// POPULATE EVENT DT STAMP ///////////////////////////////////////////////////////////
		$eventObject->setDtStamp(\Engine\DateTime::create());

		//////////// POPULATE EVENT START DATE /////////////////////////////////////////////////////////
		$eventObject->setDtStart(\Engine\DateTime::createFromIsoDate($departureDateTimeObject->format('Y-m-d')));

		/////////// POPUlATE EVENT END DATE ///////////////////////////////////////////////////////////
		$arrivalDateTimeObject = $chosenOfferObject->destinationDateTime;
		if ($arrivalDateTimeObject) {
			$eventObject->setDtEnd(\Engine\DateTime::createFromIsoDate($arrivalDateTimeObject->format('Y-m-d')));
		}

		///////// POPULATE EVENT LOCATION ///////////////////////////////////////////////////////////
		$destinationName = $this->getDestinationName($destinationPlaceObject);
		if ($destinationName) {
			$eventObject->setLocation($destinationName);
		}

		////////// POPULATE EVENT DESCRIPTION ///////////////////////////////////////////////////////

		// compose description
		$description = '';

		// get supplier product object
		$supplierProductObject = $chosenOfferObject->supplierProduct;

		if ($supplierProductObject) {
			$categoryName = $supplierProductObject->categoryCode;
			$name = $supplierProductObject->name;
			$address = $supplierProductObject->address;

			$supplierProductPlaceObject = $supplierProductObject->place;
			$supplierProductPlaceName = $this->getDestinationName($supplierProductPlaceObject);

			if ($name) {
				$description .= sprintf("Location: %s", $name);
			}

			if ($categoryName) {
				$description .= sprintf("(%s)", $categoryName);
			}

			if ($supplierProductPlaceName) {
				$description .= sprintf(", %s", $supplierProductPlaceName);
			}

			if ($address) {
				$description .= sprintf(", %s", $address);
			}
		}

		// get multiplier
		$multiplers = $chosenOfferObject->multipliers;
		foreach ($multiplers as $type => $details) {
			$description .= sprintf(", %s X %s", $details['count'], $type);
		}

		$description .= sprintf("\nStart date: %s\n", $departureDateTimeObject->formatDateStd());
		if ($arrivalDateTimeObject) {
			$description .= sprintf("End date: %s\n", $arrivalDateTimeObject->formatDateStd());
		}

		$eventObject->setDescription($description);
	}

	/**
	 * Populate event object from itinerary segment object
	 * @param \App\ImportedOrder\Itinerary_Segment $segmentObject
	 * @param \App\Utils\Calendar\Event $eventObject
	 * @throws \RuntimeException
	 */
	private function populateEventFromItinerarySegment(\App\ImportedOrder\Itinerary_Segment $segmentObject, \App\Utils\Calendar\Event $eventObject)
	{
		// get departure date time object
		$departureDateTimeObject = $segmentObject->departureDateTime;

		////////// POPULATE EVENT UNIQUE ID ////////////////////////////////////////////////////////
		$eventObject->setUid(sprintf("%sZ-%s-%s",
				\Engine\DateTime::create()->format('Ymd\THis'),
				\Engine\RandomGenerator::randomString(5),
				\Engine\RandomGenerator::randomFloat(10, 15)
		));

		/////////// POPULATE EVENT SUMMARY ////////////////////////////////////////////////////////////
		// arrival details
		$arrivalPlaceObj = $segmentObject->arrivalPlace;
		$summary = $this->getSummary($arrivalPlaceObj);
		$eventObject->setSummary($summary);

		///////// POPULATE EVENT LOCATION ///////////////////////////////////////////////////////////
		$destinationName = $this->getDestinationName($arrivalPlaceObj);
		if ($destinationName) {
			$eventObject->setLocation($destinationName);
		}

		///////////// POPULATE EVENT DT STAMP ///////////////////////////////////////////////////////////
		$eventObject->setDtStamp(\Engine\DateTime::create());

		//////////// POPULATE EVENT START DATE /////////////////////////////////////////////////////////
		$eventObject->setDtStart($departureDateTimeObject);

		/////////// POPULATE EVENT END DATE ///////////////////////////////////////////////////////////
		$arrivalDateTimeObject = $segmentObject->arrivalDateTime;
		if ($arrivalDateTimeObject) {
			$eventObject->setDtEnd($arrivalDateTimeObject);
		}


		////////// POPULATE EVENT DESCRIPTION ///////////////////////////////////////////////////////

		// get transport number
		$transportNumber = $segmentObject->transportNumber;

		// get seat number
		$seatNumber = $segmentObject->seatNumber;

		// get distance
		$distance = $segmentObject->distance;
		$distanceUnit = $segmentObject->distanceUnit;

		// compose description
		$description = '';

		$description .= sprintf("Departure time: %s\n", $departureDateTimeObject->format('d-m-Y H:i:s'));
		if ($arrivalDateTimeObject) {
			$description .= sprintf("Arrival time: %s\n", $arrivalDateTimeObject->format('d-m-Y H:i:s'));
		}

		$description .= sprintf("PNR: %s\n", $this->importedServiceEntity->offerExternalSystemReservationId);

		if ($transportNumber) {
			$description .= sprintf("Transportation number (flight): %s\n", $transportNumber);
		}
		if ($seatNumber) {
			$description .= sprintf("Seat number: %s\n", $seatNumber);
		}
		if ($distance) {
			$description .= sprintf("Flight distance: %s %s\n", $distance, $distanceUnit);
		}

		$eventObject->setDescription($description);
	}

	/**
	 * Determine the destination name
	 * @param \App\ImportedOrder\Place $destinationObject
	 * @return NULL|String
	 */
	private function getDestinationName(?\App\ImportedOrder\Place $destinationObject=NULL)
	{
		if ($destinationObject) {
			$matchedArrivalPlace = $destinationObject->getMatchedId($this->importedServiceEntity->idSystem);

			if ($matchedArrivalPlace['cityId']) {
				return \Entity\City::select($matchedArrivalPlace['cityId'])->nameStandard;
			}

			if ($matchedArrivalPlace['countryCode']) {
				return \Entity\Country::select($matchedArrivalPlace['countryCode'])->nameStandard;
			}
		}

		return NULL;
	}

	/**
	 * Determine the event summary
	 * @param \App\ImportedOrder\Place $destinationObject
	 * @return string
	 */
	private function getSummary(?\App\ImportedOrder\Place $destinationObject=NULL)
	{
		$summary = "Your trip details";

		if ($destinationObject) {
			// get matched details
			$destinationName = $this->getDestinationName($destinationObject);

			if ($destinationName) {
				$summary = sprintf("Your trip details to %s", $destinationName);
			}
		}

		return $summary;
	}
}