<?php

namespace Planaday\Database\SQLDatabaseControllers\Booking;

use Planaday\Database\Abstraction\SQLQuery\ColumnTypeMap;
use Planaday\Database\Abstraction\SQLQuery\SQLFactory;
use Planaday\Database\SQLDatabaseControllers\Table;
use Planaday\Entities\Booking\DTO\Address;
use Planaday\Platform\PlatformAbstraction\DatabaseInterface;

class BookingAddressTable extends Table {
	public const BOOKING_ADDRESS_TABLE = 'booking_address';

	public const ID_COLUMN = 'id';
	public const NAME_COLUMN = 'name';
	public const STREET_COLUMN = 'street';
	public const HOUSE_NUMBER_COLUMN = 'house_number';
	public const HOUSE_NUMBER_EXTENSION_COLUMN = 'house_number_extension';
	public const CITY_COLUMN = 'city';
	public const COUNTRY_COLUMN = 'country';
	public const POSTAL_CODE_COLUMN = 'postal_code';

	public function __construct( DatabaseInterface $querySender, SQLFactory $sql, ColumnTypeMap $columnTypeMap ) {
		$columns = [];

		$columns[self::ID_COLUMN] = implode(" ", [
			$columnTypeMap->ID(),
			$columnTypeMap->NOT_NULL(),
			$columnTypeMap->AUTO_INCREMENT(),
			$columnTypeMap->PRIMARY_KEY()
		]);

		$columns[self::NAME_COLUMN] = implode(" ", [
			$columnTypeMap->NAME(),
			$columnTypeMap->DEFAULT_NULL()
		]);

		$columns[self::STREET_COLUMN] = implode(" ", [
			$columnTypeMap->STREET(),
			$columnTypeMap->DEFAULT_NULL()
		]);

		$columns[self::HOUSE_NUMBER_COLUMN] = implode(" ", [
			$columnTypeMap->HOUSE_NUMBER(),
			$columnTypeMap->DEFAULT_NULL()
		]);

		$columns[self::HOUSE_NUMBER_EXTENSION_COLUMN] = implode(" ", [
			$columnTypeMap->HOUSE_NUMBER_EXTENSION(),
			$columnTypeMap->DEFAULT_NULL()
		]);

		$columns[self::CITY_COLUMN] = implode(" ", [
			$columnTypeMap->CITY(),
			$columnTypeMap->DEFAULT_NULL()
		]);

		$columns[self::COUNTRY_COLUMN] = implode(" ", [
			$columnTypeMap->COUNTRY(),
			$columnTypeMap->DEFAULT_NULL()
		]);

		$columns[self::POSTAL_CODE_COLUMN] = implode(" ", [
			$columnTypeMap->ZIPCODE(),
			$columnTypeMap->DEFAULT_NULL()
		]);

		parent::__construct( $querySender, $sql, self::BOOKING_ADDRESS_TABLE, $columns, [] );
	}

	/**
	 * @param Address $address
	 *
	 * @return int id of created address if new address, otherwise id of existing address
	 */
	public function set(Address $address):int {
		$table = $this->getSqlTable();
		$array = $this->addressObjectToArray($address);

		if ($address->getDatabaseId() !== null && $this->querySender->idExists($this, $address->getDatabaseId())) {
			$where = $this->sql->compare($table->getColumn(self::ID_COLUMN), $address->getDatabaseId(), true);
			$query = $this->sql->update($table, $where, $array);

			$this->querySender->sendQuery($query->toQuery());

			return $address->getDatabaseId();
		}

		$query = $this->sql->insert($table, $array);
		$this->querySender->sendQuery($query->toQuery());

		$address->setDatabaseId($this->querySender->getLastGeneratedInsertId());
		return $address->getDatabaseId();
	}

	public function remove(int $id):void {
		$table = $this->getSqlTable();
		$where = $this->sql->compare( $table->getColumn( self::ID_COLUMN ), $id, true );
		$query = $this->sql->delete( $table, $where );

		$this->querySender->sendQuery( $query->toQuery() );
	}

	public function get(int $id): ?Address {
		$table = $this->getSqlTable();
		$where = $this->sql->compare($table->getColumn(self::ID_COLUMN), $id, true);
		$query = $this->sql->query($table, $table);
		$query->setWhere($where);
		$query->setLimit(1);

		$result = $this->querySender->sendQuery($query->toQuery());
		if (!is_array($result) || count($result) < 1) {
			$this->logWarning("No address found with id $id", $result);
			return null;
		}

		return $this->addressArrayToObject($result[0]);
	}

	public function addressObjectToArray(Address $address): array {
		$returnArray = [];

		$returnArray[ self::NAME_COLUMN ] = $address->getName();
		$returnArray[ self::STREET_COLUMN ] = $address->getStreet();
		$returnArray[ self::HOUSE_NUMBER_COLUMN ] = $address->getHouseNumber();
		$returnArray[ self::HOUSE_NUMBER_EXTENSION_COLUMN ] = $address->getHouseNumberExtension();
		$returnArray[ self::CITY_COLUMN ] = $address->getCity();
		$returnArray[ self::COUNTRY_COLUMN ] = $address->getCountry();
		$returnArray[ self::POSTAL_CODE_COLUMN ] = $address->getPostalCode();

		return $returnArray;
	}

	public function addressArrayToObject(array $array): Address {
		return (new Address())
			->setName( $array[ self::NAME_COLUMN ] )
			->setStreet( $array[ self::STREET_COLUMN ] )
			->setHouseNumber( $array[ self::HOUSE_NUMBER_COLUMN ] )
			->setHouseNumberExtension( $array[ self::HOUSE_NUMBER_EXTENSION_COLUMN ] )
			->setCity( $array[ self::CITY_COLUMN ] )
			->setCountry( $array[ self::COUNTRY_COLUMN ] )
			->setPostalCode( $array[ self::POSTAL_CODE_COLUMN ] )
			->setDatabaseId( $array[ self::ID_COLUMN ] );
	}
}