<?php

namespace App\Classes\FTN\Packet;

use Illuminate\Support\Arr;

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';

	/**
	 * Create our message packet header
	 */
	protected function header(): string
	{
		try {
			return pack(collect(self::HEADER)->pluck(1)->join(''),
				$this->ff,					// Orig Node
				$this->tf,							// Dest Node
				$this->fp,							// Orig Point
				$this->tp,							// Dest Point
				'',									// Reserved
				2,									// Sub Version (should be 2)
				2,									// Packet Version (should be 2)
				$this->fn,							// Orig Net
				$this->tn,							// Dest Net
				(Setup::PRODUCT_ID & 0xff),			// Product Code
				Setup::PRODUCT_VERSION_MAJ,			// Product Version
				$this->password,					// Packet Password
				$this->fz,							// Orig Zone
				$this->tz,							// Dest Zone
				$this->fd,							// Orig Domain
				$this->td,							// Dest Domain
				strtoupper(hexstr(Setup::PRODUCT_ID)),	// ProdData
			);

		} catch (\Exception $e) {
			return $e->getMessage();
		}
	}

	/**
	 * 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'))
		);
	}
}