<?php

namespace App\ImportedOrder;

class Itinerary_Segment extends EntityAbstract
{

	/**
	 * Segment departure place.
	 * @var \App\ImportedOrder\Place
	 */
	public ?\App\ImportedOrder\Place $departurePlace = null;

	/**
	 * Segment arrival place.
	 * @var \App\ImportedOrder\Place
	 */
	public ?\App\ImportedOrder\Place $arrivalPlace = null;

	/**
	 * The segment departure date and time.
	 * @var ?\Engine\DateTime
	 */
	public ?\Engine\DateTime $departureDateTime = null;

	/**
	 * The segment arrival date and time.
	 * @var ?\Engine\DateTime
	 */
	public ?\Engine\DateTime $arrivalDateTime = null;

	/**
	 * The segment duration.
	 * @var String
	 */
	public $duration;

	/**
	 * The segment distance.
	 * @var Float
	 */
	public $distance;

	/**
	 * The segment distance unit - km/miles.
	 * @var String
	 */
	public $distanceUnit;

	/**
	 * The segment transport number.
	 * @var String
	 */
	public $transportNumber;

	/**
	 * The segment transport unit (plane/bus type).
	 * @var String
	 */
	public $transportUnit;

	/**
	 * The seat number for this segment.
	 * @var String
	 */
	public $seatNumber;

	/**
	 * The segment class code.
	 * @var String
	 */
	public $classCode;

	/**
	 * The segment class name.
	 * @var String
	 */
	public $className;

	/**
	 * The segment supplier object. For ticketing in GDSs this is the marketing carrier.
	 * @var \App\ImportedOrder\Supplier
	 */
	public ?\App\ImportedOrder\Supplier $supplier = null;

	/**
	 * The segment operated by object. Most GDS's contain this.
	 * This should have been a reference from the imported order, but we do not validate it, so
	 * it just has to be a supplier object.
	 * @var \App\ImportedOrder\Supplier
	 */
	public ?\App\ImportedOrder\Supplier $operatedBy = null;

	/**
	 * Indicates if the starting point of the segment allows stop-over.
	 * @var Boolean
	 */
	public $stopOverAllowed;

	/**
	 * The number of stops
	 * @var Integer
	 */
	public $stopCounts;

	/**
	 * The segment's fare basis code.
	 * @var String
	 */
	public $fareBasis;

	/**
	 * The segment's ticket designator
	 * @var string
	 */
	public $ticketDesignator;

	/**
	 * The meal code(eg:L)
	 * @var string
	 */
	public $mealCode;

	/**
	 * The meal description(human readable format)
	 * @var String
	 */
	public $mealDescription;

	/**
	 * The baggage code
	 * @var string
	 */
	public $baggageCode;

	/**
	 * The terminal for check in
	 * @var string
	 */
	public $terminalCheckIn;

	/**
	 * The terminal for checkout
	 * @var string
	 */
	public $terminalCheckOut;

	/**
	 * The supplier record locator
	 * @var string
	 */
	public $supplierRecordLocator;

	/**
	 * The CO² emissions in Kg
	 * @var float
	 */
	public $co2Emissions;

	/**
	 * The list of ssr records associated to this segment
	 * @var \App\ImportedOrder\Itinerary_SSRRecord[]
	 */
	public ?array $ssrRecords = null;


	/**
	 * Adds a new SSR record on this segment
	 * @param Itinerary_SSRRecord $ssrRecord
	 * @throws \Exception
	 */
	public function addSSRRecord(Itinerary_SSRRecord $ssrRecord)
	{
		if ($this->ssrRecordExists($ssrRecord)) {
			throw new \Exception('There is a SSR record that was attached twice to an itinerary segment.');
		}
		if (!$this->ssrRecords) {
			$this->ssrRecords = [];
		}

		$this->ssrRecords[] = $ssrRecord;
	}

	/**
	 * Check if a ssr record object exists on this segment
	 * @param Itinerary_SSRRecord $ssrRecord
	 * @return boolean
	 */
	public function ssrRecordExists(Itinerary_SSRRecord $ssrRecord) :bool
	{
		if (!$this->ssrRecords) {
			return false;
		}
		foreach ($this->ssrRecords as $ssrRecordObj) {
			if ($ssrRecord === $ssrRecordObj) {
				return true;
			}
		}
		return false;
	}


	/**
	 * (non-PHPdoc)
	 * @see \App\ImportedOrder\EntityAbstract::validateEntityFields()
	 */
	protected function validateEntityFields(\App\MessagesCollector $messagesCollector): void
	{
	    $CFG = \Engine\Loader_Cfg::getInstance()->getGlobal();

		if ($this->duration and !\Engine\Validator::set($this->duration)->isTime()) {
			$messagesCollector->addInfo('The duration is not valid.');
		}
		if ($this->distance) {
			if (!is_numeric($this->distance) or $this->distance<0) {
				$messagesCollector->addInfo('The distance must be a positive number.');
			}
			if (!in_array($this->distanceUnit, ['km', 'miles']) ) {
				$messagesCollector->addInfo('The distance unit must be `km` or `miles`.');
			}
		}

		// check class name
		if ($this->className and !in_array($this->className, $CFG['travel']['transportSegmentClassNames'])) {
			$messagesCollector->addInfo('The class name is not valid.');
		}

		// check departure/arrival DateTime
		if ($this->departureDateTime and !$this->departureDateTime->isValid()) {
			$messagesCollector->addInfo('The departure date/time is not valid.');
		}
		if ($this->arrivalDateTime and !$this->arrivalDateTime->isValid()) {
			$messagesCollector->addInfo('The arrival date/time is not valid.');
		}

		// append extra validators
		if ($this->departurePlace) {
			$messagesCollector->appendMessages($this->departurePlace->getValidatingMessagesCollector(), 'Departure place: %s');
		}
		if ($this->arrivalPlace) {
			$messagesCollector->appendMessages($this->arrivalPlace->getValidatingMessagesCollector(), 'Arrival place: %s');
		}
		if ($this->supplier) {
			$messagesCollector->appendMessages($this->supplier->getValidatingMessagesCollector(), 'Supplier: %s');
		}
		if ($this->operatedBy) {
			$messagesCollector->appendMessages($this->operatedBy->getValidatingMessagesCollector(), 'OperatedBy: %s');
		}

		// check ssr record
		if ($this->ssrRecords) {
			foreach ($this->ssrRecords as $idx => $ssrRecord) {
				// check supplier
				$messagesCollector->appendMessages($ssrRecord->getValidatingMessagesCollector(), "SSR record #".($idx+1).": %s");
			}
		}
	}
}
