<?php

	namespace Icing\Model\Entity;

	use Cake\Utility\Inflector;

	/**
	 * @property string prefix
	 * @property string title
	 * @property string first_name
	 * @property string given_name
	 * @property string middle_name
	 * @property string last_name
	 * @property string family_name
	 * @property string suffix
	 * @property string full_name
	 * @property string name
	 */
	class ContactName
	{

		protected array $_data = [];

		const PREFIX_LIST = [
			"Mr.",
			"Mrs.",
			"Miss",
			"Ms.",
			"Dr.",
			"Prof.",
			"Rev.",
			"Hon.",
			"Pres.",
			"Gov.",
			"Sen.",
			"Rep.",
			"Amb.",
			"Gen."
		];

		const SUFFIX_LIST = [
			"Jr.",
			"Sr.",
			"II",
			"III",
			"IV",
			"V",
			"VI",
			"VII",
			"VIII",
			"IX",
			"X"
		];

		public function __construct($name)
		{
			if (is_scalar($name)) {
				$name = ['full_name' => $name];
			}
			$this->_data = $name;
		}

		public function __get(string $prop)
		{
			$prop = Inflector::underscore($prop);
			if (isset($this->_data[$prop])) {
				return trim($this->_data[$prop]);
			}
			if (method_exists($this, $prop)) {
				return trim($this->{$prop}());
			}
			return null;
		}

		public function full_name(): string
		{
			return implode(
				' ',
				array_filter([
					$this->prefix,
					$this->first_name,
					$this->middle_name,
					$this->last_name,
					$this->suffix,
				])
			);
		}

		public function name(): string
		{
			if (isset($this->_data['first_name']) || isset($this->_data['last_name'])) {
				return implode(
					' ',
					array_filter([
						$this->_data['first_name'],
						$this->_data['last_name'],
					])
				);
			}
			$name = $this->full_name;
			if ($this->prefix) {
				$name = substr($name, strlen($this->prefix));
			}
			if ($this->suffix) {
				$name = substr($name, 0, strlen($name) - strlen($this->suffix));
			}
			return $name;
		}

		public function prefix(): string
		{
			if (isset($this->_data['title'])) {
				return $this->_data['title'];
			}
			$prefix = explode(' ', $this->full_name)[0] ?? '';
			if (in_array($prefix, self::PREFIX_LIST)) {
				return $prefix;
			}
			return '';
		}

		public function title(): string
		{
			return $this->prefix;
		}

		public function first_name(): string
		{
			return strrev(array_reverse(explode(' ', strrev($this->name), 3))[0] ?? '');
		}

		public function given_name(): string
		{
			return $this->first_name;
		}

		public function middle_name(): string
		{
			$parts = explode(' ', strrev($this->name), 3);
			if (count($parts) === 3) {
				return strrev($parts[1]);
			}
			return array_reverse(explode(' ', $this->name))[1] ?? '';
		}

		public function last_name(): string
		{
			return array_reverse(explode(' ', $this->name))[0] ?? '';
		}

		public function family_name(): string
		{
			return $this->last_name;
		}

		public function suffix(): string
		{
			$parts = explode(' ', $this->full_name);
			if (empty($parts)) {
				return '';
			}
			$suffix = $parts[count($parts) - 1];
			if (in_array($suffix, self::SUFFIX_LIST)) {
				return $suffix;
			}
			return '';
		}

		public function __toString(): string
		{
			return $this->toString();
		}

		public function toString(): string
		{
			return $this->name ?? '';
		}

		public function toArray(): array
		{
			return [
				'full_name' => $this->full_name,
				'name' => $this->name,
				'prefix' => $this->prefix,
				'first_name' => $this->first_name,
				'middle_name' => $this->middle_name,
				'last_name' => $this->last_name,
				'suffix' => $this->suffix,
			];
		}


	}
