<?php

namespace App\Config;

/**
 * The class is used for managing the fields of the supplier invoices (each field depend on the
 * service code of that particular invoice row. When using "set", the class will update ALL the services.
 * @author Gabriel Grosu
 */
class SupplierInvoice_Fields extends XmlBasicAbstract {

	/**
	 * Stores the configuration file (relative to the "files/config/" dir). For config files stored
	 * inside subdirectories, the subdirectory is included (Ex: services/servicesList.xml).
	 * @var String
	 */
	protected $fileName=CONFIG_FILE_SUPPLIERINVOICES_FIELDS;

	/**
	 * The allowed fields for supplier invoice rows.
	 * @var array
	 */
	private $allowedFields= ['rowType', 'location', 'contractNumber', 'passenger', 'reservationCode', 'reservationNumber', 'reservationId', 'idService', 'checkIn', 'checkOut', 'supplierService', 'ticketNo', 'extResId', 'extResDate', 'confirmationNumber'];

	/**
	 * (non-PHPdoc)
	 * @see \App\Config\XmlBasicAbstract::getAll_rawData_extractDataFromFile()
	 */
	protected function getAll_rawData_extractDataFromFile(\SimpleXMLElement $xml)
	{
		$return=[];
		foreach ($xml->service  as $serv) {
			// determine the current service code / fields
			$atrsList=[];
			$serviceCode=null;
			foreach ($serv->attributes() as $atr=>$val) {
				if ($atr=='code') {
					$serviceCode=(String)$val;
				} else {
					$atrsList[(String)$atr]=(String)$val;
				}
			}
			// associate this service fields
			if ($serviceCode!==null) {
				$return[$serviceCode]=$atrsList;
			}
		}

		return $return;
	}

	/**
	 * Set single field
	 * @param String $key - the service code
	 * @param String $field - the field name
	 * @param String ('','optional','mandatory') $value
	 * @throws \Exception - if input is bad
	 */
	public function setField($serviceCode, $field, $value)
	{
		// check constructor type
		if ($this->constructType!='admin') {
			throw new \Exception("You can use the method `".get_called_class().'::'.__FUNCTION__."` only if the constructor type is `admin`.");
		}
		// check inputs
		if (!is_string($serviceCode) and !is_numeric($serviceCode)) {
			throw new \Exception("You did not set() a correct code for the service code.");
		}
		if (!is_string($field) and !is_numeric($field)) {
			throw new \Exception("You did not set() a correct name for the field.");
		}

		// (re)set one key
		$this->itemsList[$serviceCode][$field] = $value;

		// update the changed flag
		$this->changedFlag = true;
	}


	/**
	 * Returns the allowed fields for supplier invoice rows.
	 * @return Array
	 */
	public function getAllowedFields()
	{
		return $this->allowedFields;
	}


	/**
	 * (non-PHPdoc)
	 * @see \App\Config\BaseAbstract::save_check()
	 */
	protected function save_check()
	{

		// LOOP THROUGH EACH REQUESTED SERVICE AND CHECK THEIR OPTIONS ////////////////////////////
		foreach ($this->itemsList as $serviceCode=>$serviceFields) {

			// check fields var
			if (!is_array($serviceFields)) $this->addErrorMessage(sprintf('The configuration for the service code `%s` is not valid.', $serviceCode));
			// check fields list
			foreach ($serviceFields as $fld=>$type) {
				if (!in_array($fld, $this->allowedFields)) $this->addErrorMessage(sprintf('The field `%s` for the service code `%s` is not valid.', $fld, $serviceCode));
				if ($type and $type!='mandatory' and $type!='optional') $this->addErrorMessage(sprintf('Bad value for the field `%s` of the service code `%s`.', $fld, $serviceCode));
			}
		}
	}


	/**
	 * (non-PHPdoc)
	 * @see \App\Config\XmlBasicAbstract::save_write_do_getXml()
	 */
	protected function save_write_do_getXml()
	{

		// start composing the XML object
		$xml = simplexml_load_string('<?xml version="1.0" encoding="UTF-8"?><supplierInvoicesFields/>');

		// LOOP THROUGH EACH SERVICE AND SET THE NEW FIELDS ---------------------------------------
		foreach ($this->itemsList as $serviceCode=>$fields) {
			if(Services_Basic::getInstance()->checkService($serviceCode) || $serviceCode == '') {
				$servObj = $xml->addChild('service');
				// add the service code attribute
				$servObj['code'] = $serviceCode;
				// set the other fields for this service
				foreach ($fields as $fld=>$visibility) {
					if ($visibility) $servObj[$fld]=$visibility;
				}
			}
		}

		// return the simplexml object
		return $xml;

	}

}