<?php
namespace App\Amadeus\FileParser;

/**
 * Parser for the MISC lines
 * @author Lucian
 */
class Line_U_17 extends \App\Amadeus\FileParser\Line_U_10
{
	/**
	 * 4.51. U- Miscellaneous Segment
	 * see page 155(197)
	 *
	 * This segment is used for any miscellaneous item an agent may want to appear in an itinerary or invoice.
	 */
	protected $structure_17 = [
		['name'=> 'MSGTAG',  'val' => 'U-',    'type' => 'AN',   'req' => 'M',  'len' => 2,],                          // 1 : Message Tag (U-)
		['name'=> 'TTONBR',                    'type' => 'N',    'req' => 'M',  'len' => 3,],                          // 2 : Tattoo Number in the PNR
		['name'=> 'DATAMODI',                  'type' => 'AN',                  'len' => 1,],                          // 3 : Modification indicator.N = segment/element newly created,M = segment/element modified,U = segment/element unchangedX = modification indicator not available for the segment/element
		['name'=> 'DELIM',   'val' => ';',     'type' => 'AN',   'req' => 'M',  'len' => 1,],                          // 4 : Delimiter (Constant value of ';')
		['name'=> 'SEGNBR',                    'type' => 'N',    'req' => 'M',  'len' => 3,],                          // 5 : Segment number in the PNR
		['name'=> 'SEGID',   'val' => 'MIS',   'type' => 'AN',   'req' => 'M',  'len' => 3,],                          // 6 : Segment Identifier Tag (Constant value of 'MIS')
		['name'=> 'DELIM',   'val' => ' ',     'type' => 'AN',   'req' => 'M',  'len' => 1,],                          // 7 : Delimiter (Constant value of blank)
		['name'=> 'SUPPCDE',                   'type' => 'AN',   'req' => 'M',  'len_min' => 2,   'len_max' => 4,],    // 8 : Airline/Supplier Code
		['name'=> 'DELIM',   'val' => ' ',     'type' => 'AN',   'req' => 'M',  'len' => 1,],                          // 9 : Delimiter (Constant value of blank)
		// renamed from STATNBR, because in all other U types, this is called STATUS, and the parser expects it like this
		['name'=> 'STATUS',                   'type' => 'AN',   'req' => 'M',  'len' => 2,],                          // 10 : Status Code
		['name'=> 'NBRSVC',                    'type' => 'N',    'req' => 'M',  'len' => 2,],                          // 11 : Number in party
		['name'=> 'DELIM',   'val' => ';',     'type' => 'AN',   'req' => 'M',  'len' => 1,],                          // 12 : Delimiter (Constant value of ';')
		['name'=> 'PNRSTAT',                   'type' => 'AN',   'req' => 'M',  'len' => 4,],                          // 13 : PNR Status Code and Number in Party
		['name'=> 'BLANK',   'val' => ' ',     'type' => 'AN',   'req' => 'M',  'len' => 1,],                          // 14 : Delimiter (Constant value of blank)
		['name'=> 'DATE',                      'type' => 'D:DDMMM,DDMMMYYYY:PNRDTE','req' => 'M',],                            // 15 : DATE (DDMMM)
		['name'=> 'DELIM',   'val' => ';',     'type' => 'AN',   'req' => 'M',  'len' => 1,],                          // 16 : Delimiter (Constant value of ';')
		['name'=> 'CTYCDE',                    'type' => 'AN',   'req' => 'M',  'len_min' => 3,   'len_max' => 5,],    // 17 : City Code
		['name'=> 'DELIM',   'val' => ';',     'type' => 'AN',   'req' => 'M',  'len' => 1,],                          // 18 : Delimiter (Constant value of ';')
		['name'=> 'CITY',                      'type' => 'AN',                  'len_min' => 3,   'len_max' => 17,],   // 19 : City Name
		['name'=> 'DELIM',   'val' => ';',     'type' => 'AN',   'req' => 'M',  'len' => 1,],                          // 20 : Delimiter (Constant value of ';')
		['name'=> 'FREE',                      'type' => 'AN',],                                                       // 21 : Free Flow Data
		['name'=> 'DELIM',   'val' => ';',     'type' => 'AN',   'req' => 'M',  'len' => 1,],                          // 22 : Delimiter (Constant value of ';')
		['name'=> 'FLNTAG',                    'type' => 'AN',                  'len' => 4,],                          // 23 : FLWN' (flown/past date segment tag when present in the PNR)
		['name'=> 'PSGASS',  'val' => ';P',    'type' => 'ASSOC',],
	];

	/**
	 * (non-PHPdoc)
	 * @see \App\Amadeus\FileParser\Line_U_10::postParse()
	 */
	protected function postParse()
	{
		parent::postParse();

		// CABFORCE segment
		if ($this->tree['_type'] == '17' && preg_match("/^\/TYP\-CAB\/.+\/CABFORCE_[0-9]+$/", $this->tree['FREE'])) {
						$FREE = explodeClean("/", $this->tree['FREE']);
			foreach ($FREE as $rawTag) {
				$this->tree['FREE_']['_type'] = 'CABFORCE';

				$matches = [];
				preg_match("/^(?P<key>[A-Z]{2,3})-(?P<value>.*)$/", $rawTag, $matches);
				if ($matches['key']) {
					switch ($matches['key']) {
						case 'TYP':		// type of service
							$this->tree['FREE_']['typeOfService'] = $matches['value'];
						break;

						case 'PU':		// pick-up location
							$this->tree['FREE_']['pickupLocation'] = $matches['value'];
						break;
						case 'PD':		// pick-up date
							$this->tree['FREE_']['pickupDate'] = self::extractDate($matches['value'], "DDMMMYY", ['referenceDate'=>$this->parser->getStructure()->D->PNRDTE]);
						break;
						case 'PT':		// pick-up time
							$this->tree['FREE_']['pickupTime'] = self::extractHour($matches['value'], "hhmm");
						break;

						case 'DO':		// pick-up date
							$this->tree['FREE_']['dropoffLocation'] = $matches['value'];
						break;
						case 'DD':		// pick-up time
							$this->tree['FREE_']['dropoffDate'] = self::extractDate($matches['value'], "DDMMMYY", ['referenceDate'=>$this->parser->getStructure()->D->PNRDTE]);
						break;
						case 'TTL':		// total price of service
							$matches2 = [];
							preg_match("/^(?P<amount>[0-9\.]+)(?P<currency>[A-Z]{3})$/", $matches['value'], $matches2);
							$this->tree['FREE_']['totalPriceAmount'] = $matches2['amount'];
							$this->tree['FREE_']['totalPriceCurrency'] = $matches2['currency'];
						break;

						default:
							$this->parser->addLog(__METHOD__.": The FREE line contains the '{$matches['key']}' key that i dont know how to parse[1]");
						break;
					}
				}
				elseif (preg_match("/^(?P<rawConfNumber>CABFORCE_(?P<confNumber>[0-9]+))$/", $rawTag, $matches)) {
					$this->tree['FREE_']['confNumber'] = $matches['confNumber'];
				}
				else {
					$this->parser->addLog(__METHOD__.": The FREE CABFORCE line contains the '{$rawTag}' raw tag that i dont know how to split & parse[2]");
				}
			}
		}



		// PASSIVE TRAIN segment
		if ($this->tree['_type'] == '17' && preg_match("/^\/TRN\-/", $this->tree['FREE'])) {
						$FREE = explodeClean("/", $this->tree['FREE']);
			/*
			 * the 1 example I got, had it's FREE line like:
			 * 	TRN-NS INTL-CPFVLPH/20190723-1115/20190806-1115/NLASC/20190806-1435/FRPNO/9340/1/ /180.00-EUR/PAX1/
			 *      [0]              [1]           [2]           [3]    [4]          [5]   [6][7][8][9]       [10]
			 * this seems to be a index-based line, where:
			 * 	- supplier: NS INTL
			 *  - confirmation number: CPFVLPH
			 *  - departure 6th of August 2019 at 11:15 from the station ASC from Netherlands (NL)
			 *  - it arrives of 6th of August 2019 at 14:35 in PNO from France (FR)
			 *  - train number: 9340
			 *  - cost: 180 EUR
			 *
			 *
			 *
			 * @see JIRA:TD-5747
			 * */
			if (count($FREE)==11) {
				foreach ($FREE as $k=>$v) {
					$FREE[$k] = explode("-", $FREE[$k]);
				}

				$this->tree['FREE_']['_type'] = 'train';

				$this->tree['FREE_']['supplierCode'] = 		$FREE[0][1];
				$this->tree['FREE_']['confirmationNumber'] =$FREE[0][2];

				$this->tree['FREE_']['bookingDate'] = 		self::extractDate($FREE[1][0], "YYYYMMDD", ['referenceDate'=>$this->parser->getStructure()->D->PNRDTE]);
				$this->tree['FREE_']['bookingHour'] = 		self::extractHour($FREE[1][1], "hhmm");

				$this->tree['FREE_']['departureDate'] = 	self::extractDate($FREE[2][0], "YYYYMMDD", ['referenceDate'=>$this->parser->getStructure()->D->PNRDTE]);
				$this->tree['FREE_']['departureHour'] = 	self::extractHour($FREE[2][1], "hhmm");

				$this->tree['FREE_']['departureCountry'] = 	substr($FREE[3][0], 0, 2);
				$this->tree['FREE_']['departureStation'] = 	substr($FREE[3][0], 2, 3);

				$this->tree['FREE_']['arrivalDate'] = 		self::extractDate($FREE[4][0], "YYYYMMDD", ['referenceDate'=>$this->parser->getStructure()->D->PNRDTE]);
				$this->tree['FREE_']['arrivalHour'] = 		self::extractHour($FREE[4][1], "hhmm");

				$this->tree['FREE_']['arrivalCountry'] = 	substr($FREE[5][0], 0, 2);
				$this->tree['FREE_']['arrivalStation'] = 	substr($FREE[5][0], 2, 3);

				$this->tree['FREE_']['trainNumber'] = 		$FREE[6][0];

				$this->tree['FREE_']['supplierPrice'] = 	(float)$FREE[9][0];
				$this->tree['FREE_']['supplierCurrency'] = 	$FREE[9][1];
			}
			else {
				$this->parser->addLog(__METHOD__.": The FREE Train line contains ".count($FREE)." fields, and I don't know how to handle these");
			}
		}

		// HOTEL segment, JIRA: TD-6423([Incomplete] We should interpret RU passive segments from MISC rows -#35283)
		if ($this->tree['_type'] == '17' && preg_match("/^HOTEL\-/", $this->tree['FREE'])) {
						$FREE = explodeClean("/", $this->tree['FREE']);
			foreach ($FREE as $rawTag) {
				$this->tree['FREE_']['_type'] = 'hotel';

				$matches = [];
				preg_match("/^(?P<key>[A-Z]{2,3})-(?P<value>.*)$/", $rawTag, $matches);
				if ($matches['key']) {
					switch ($matches['key']) {
						case 'HN':
							$this->tree['FREE_']['hotelName'] = $matches['value'];
						break;
						case 'AD':
							$this->tree['FREE_']['address'] = $matches['value'];
						break;
						case 'CT':
							$this->tree['FREE_']['postalCode'] = $matches['value'];
						break;
						case 'CI':
							$this->tree['FREE_']['city'] = $matches['value'];
						break;
						case 'CY':
							$this->tree['FREE_']['country'] = $matches['value'];
						break;
						case 'IN':
							$this->tree['FREE_']['checkInDate'] = self::extractDate($matches['value'], "DDMMM", ['referenceDate'=>$this->parser->getStructure()->D->PNRDTE]);
						break;
						case 'OUT':
							$this->tree['FREE_']['checkOutDate'] = self::extractDate($matches['value'], "DDMMM", ['referenceDate'=>$this->parser->getStructure()->D->PNRDTE]);
						break;
						case 'OC':
							$this->tree['FREE_']['numberOfPassengers'] = $matches['value'];
						break;
						case 'CF':
							$this->tree['FREE_']['confirmationNumber'] = $matches['value'];
						break;
						case 'CR':
							$this->tree['FREE_']['currency'] = $matches['value'];
						break;
						case 'RT':
							$this->tree['FREE_']['dailyRate'] = (float)$matches['value'];
						break;

						default:
							$this->parser->addLog(__METHOD__.": The FREE line contains the '{$matches['key']}' key that i dont know how to parse[1]");
						break;
					}
				}
				else {
					$this->parser->addLog(__METHOD__.": The FREE Transfer line contains the '{$rawTag}' raw tag that i dont know how to split & parse[2]");
				}
			}
		}

		// transfer segment
		if ($this->tree['_type'] == '17' && preg_match("/^TXI\/.+$/", $this->tree['FREE'])) {
			$FREE = explodeClean("/", $this->tree['FREE']);
			foreach ($FREE as $rawTag) {
				$this->tree['FREE_']['_type'] = 'transfer';

				$matches = [];
				preg_match("/^(?P<key>[A-Z]{2,3})-(?P<value>.*)$/", $rawTag, $matches);
				if ($matches['key']) {
					switch ($matches['key']) {
						case 'SP':		// Supplier Code
							$this->tree['FREE_']['supplierCode'] = $matches['value'];
						break;
						case 'TK':		// Confirmation number
							$this->tree['FREE_']['confirmationNumber'] = $matches['value'];
						break;
						case 'DD':		// Booking date
							if ($matches['value'][0]==" ") {
								$matches['value'][0] = "0";	// "03JAN" can be written as " 3JAN"...
							}
							$this->tree['FREE_']['bookingDate'] = self::extractDate($matches['value'], "DDMMM", ['referenceDate'=>$this->parser->getStructure()->D->PNRDTE]);
						break;
						case 'VT':		// Vehicle type
							$this->tree['FREE_']['vehicleType'] = $matches['value'];
						break;
						case 'BC':		// Booking class
							$this->tree['FREE_']['bookingClass'] = $matches['value'];
						break;

						case 'UP':		// Transfer Price
							$this->tree['FREE_']['transferPrice'] = (float)$matches['value'];
						break;
						case 'UC':		// Transfer Price Currency
							$this->tree['FREE_']['transferPriceCurrency'] = $matches['value'];
						break;

						case 'PU':		// Pick up location
							$this->tree['FREE_']['pickupLocation'] = $matches['value'];
							if (strlen($matches['value'])==3) {
								$this->tree['FREE_']['pickupLocation_type'] = 'iata';
							}
							else {
								$this->tree['FREE_']['pickupLocation_type'] = 'address';
							}
						break;

						case 'DO':		// Drop off location
							$this->tree['FREE_']['dropoffLocation'] = $matches['value'];
							if (strlen($matches['value'])==3) {
								$this->tree['FREE_']['dropoffLocation_type'] = 'iata';
							}
							else {
								$this->tree['FREE_']['dropoffLocation_type'] = 'address';
							}
						break;

						case 'PUD':		// Pick up date and time
							if ($matches['value']) {
								$this->tree['FREE_']['pickupDate'] = self::extractDate(substr($matches['value'], 0, 10), "YYYY-MM-DD", ['referenceDate'=>$this->parser->getStructure()->D->PNRDTE]);
								$this->tree['FREE_']['pickupTime'] = self::extractHour(substr($matches['value'], 11, 5), "hh:mm");
							}
						break;

						default:
							$this->parser->addLog(__METHOD__.": The FREE line contains the '{$matches['key']}' key that i dont know how to parse[1]");
						break;
					}
				}
				// TAX
				elseif (preg_match("/^(?P<tax>TAX(?P<amount>[0-9\.]+)(?P<currency>[A-Z]{3}))$/", $rawTag, $matches)) {
					$this->tree['FREE_']['taxAmount'] = (float)$matches['amount'];
					$this->tree['FREE_']['taxCurrency'] = $matches['currency'];
				}
				// TXI
				elseif (preg_match("/^TXI$/", $rawTag, $matches)) {
					// this is the line header, ignore it
				}
				else {
					$this->parser->addLog(__METHOD__.": The FREE Transfer line contains the '{$rawTag}' raw tag that i dont know how to split & parse[2]");
				}
			}
		}

		// visa segment		@JIRA TD-9320, Blue Sky EG
		if ($this->tree['_type'] == '17' && preg_match("/^ENTRY VISA SERVICE,/", $this->tree['FREE'])) {

			// TODO we might need to explode the FREE line by a delimiter

			$this->tree['FREE_']['_type'] = 'visa';

			$matches = [];
			// ENTRY VISA SERVICE,BUSINESS,SINGLE ENTRY,AFGHAN EMBASSY,PENDING,CF-12345,NOTES:INS
			if (preg_match("/^ENTRY VISA SERVICE,(?P<category>[0-9A-Z\s]*),(?P<productType>[0-9A-Z\s]*),(?P<location>[0-9A-Z.\s]*),(?P<status>[^,]*),CF-(?P<confirmationNumber>[^,]*),NOTES:(?P<notes>[^,]*)$/", $this->tree['FREE'], $matches)) {
				$this->tree['FREE_']['category'] = $matches['category'];
				$this->tree['FREE_']['productType'] = $matches['productType'];
				$this->tree['FREE_']['location'] = $matches['location'];
				$this->tree['FREE_']['status'] = $matches['status'];
				$this->tree['FREE_']['confirmationNumber'] = $matches['confirmationNumber'];
				$this->tree['FREE_']['notes'] = $matches['notes'];
			}

		}

		// meet & assist segment	@JIRA TD-9320, Blue Sky EG
		if ($this->tree['_type'] == '17' && preg_match("/^MEET & ASSIST SERVICE,/", $this->tree['FREE'])) {

			// TODO we might need to explode the FREE line by a delimiter

			$this->tree['FREE_']['_type'] = 'meetAndAssist';

			$matches = [];
			// MEET & ASSIST SERVICE,ARRIVAL TIME 1400,KL 22 20OCT CAI JNB 1300 1400,CF-12345,NOTES:COT
			if (preg_match("/^MEET & ASSIST SERVICE,ARRIVAL TIME (?P<arrivalTime>[0-9]{4}),(?P<flightDetails>[0-9A-Z\s]*),CF-(?P<confirmationNumber>[^,]*),NOTES:(?P<notes>[^,]*)$/", $this->tree['FREE'], $matches)) {
				$this->tree['FREE_']['arrivalTime'] = $matches['arrivalTime'];
				$this->tree['FREE_']['flightDetails'] = $matches['flightDetails'];
				$this->tree['FREE_']['confirmationNumber'] = $matches['confirmationNumber'];
				$this->tree['FREE_']['notes'] = $matches['notes'];
			}

		}
	}
}
