<?php

namespace App\Classes\FTN\Packet;

use Illuminate\Support\Arr;
use Illuminate\Support\Collection;

use App\Classes\FTN\Packet;
use App\Models\Setup;

/**
 * FSC-0045 http://ftsc.org/docs/fsc-0045.001
 *
 * Commonly known as Type 2.2 packets
 * Supports 5D addressing
 */
final class FSC45 extends Packet
{
	protected const HEADER = [
		'onode'			=> [0x00,'v',2],	// Orig Node
		'dnode'			=> [0x02,'v',2],	// Dest Node
		'opoint'		=> [0x04,'v',2],	// Orig Point
		'dpoint'		=> [0x06,'v',2],	// Dest Point
		'reserved'		=> [0x08,'a8',8],	// Reserved
		'subver'		=> [0x10,'v',2],	// Sub Version (should be 2)
		'type'			=> [0x12,'v',2],	// Packet Version (should be 2)
		'onet'			=> [0x14,'v',2],	// Orig Net
		'dnet'			=> [0x16,'v',2],	// Dest Net
		'prodcode'		=> [0x18,'C',1],	// Product Code
		'prodrev-maj'	=> [0x19,'C',1],	// Product Version
		'password'		=> [0x1a,'a8',8],	// Packet Password
		'ozone'			=> [0x22,'v',2],	// Orig Zone
		'dzone'			=> [0x24,'v',2],	// Dest Zone
		'odomain'		=> [0x26,'a8',8],	// Orig Domain
		'ddomain'		=> [0x2e,'a8',8],	// Dest Domain
		'proddata'		=> [0x36,'a4',4],	// ProdData
	];

	public const TYPE = '2.2';

	public function __get($key)
	{
		switch ($key) {
			case 'product':
				return Arr::get($this->header,'prodcode');

			case 'software_ver':
				return Arr::get($this->header,'prodrev-maj');

			default:
				return parent::__get($key);
		}
	}

	/**
	 * Create our message packet header
	 */
	protected function header(Collection $msgs): string
	{
		return pack(collect(self::HEADER)->pluck(1)->join(''),
			$this->fftn_p->node_id,				// Orig Node
			$this->tftn_p->node_id,						// Dest Node
			$this->fftn_p->point_id,					// Orig Point
			$this->tftn_p->point_id,					// Dest Point
			'',											// Reserved
			2,											// Sub Version (should be 2)
			2,											// Packet Version (should be 2)
			$this->fftn_p->host_id,						// Orig Net
			$this->tftn_p->host_id,						// Dest Net
			(Setup::PRODUCT_ID & 0xff),					// Product Code
			Setup::PRODUCT_VERSION_MAJ,					// Product Version
			$this->pass_p ?: $this->tftn_p->pass_packet,		// Packet Password
			$this->fftn_p->zone->zone_id,				// Orig Zone
			$this->tftn_p->zone->zone_id,				// Dest Zone
			$this->fftn_p->zone->domain->name,			// Orig Domain
			$this->tftn_p->zone->domain->name,			// Dest Domain
			strtoupper(hexstr(Setup::PRODUCT_ID)),	// ProdData
		);
	}

	/**
	 * Determine if this is a fsc-0045 packet
	 *
	 * @param string $header
	 * @return bool
	 * @throws \Exception
	 */
	public static function is_type(string $header): bool
	{
		$head = unpack(self::unpackheader(self::HEADER),$header);

		return (
			(Arr::get($head,'type') === 2)
			&& ((Arr::get($head,'opoint') === 0) || (Arr::get($head,'onet') !== 0xffff))
			&& (strlen(rtrim(Arr::get($head,'reserved'),"\x00")) === 0)
			&& (Arr::get($head,'subver') === 2)
			&& (Arr::get($head,'odomain'))
			&& (Arr::get($head,'ddomain'))
		);
	}
}