<?php

namespace App\Classes\Protocol\DNS;

use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;

use App\Classes\Protocol\DNS;

final class RR
{
	private const LOGKEY = 'PDR';

	public Collection $labels;
	public int $type;
	public int $class;
	private string $buf;

	public function __construct(string $buf)
	{
		$this->buf = $buf;
		$this->labels = collect();

		$i = 0;

		$domain = strstr($buf,"\x00",TRUE);
		$i += strlen($domain)+1;

		try {
			$this->type = Arr::get(unpack('n',substr($buf,$i,2)),1);
			$this->class = Arr::get(unpack('n',substr($buf,$i+2,2)),1);

		} catch (\ErrorException $e) {
			Log::error(sprintf('%s:! Error unpacking buffer [%s]',self::LOGKEY,$buf),['buf'=>hex_dump($buf)]);
			return;
		}

		$i += 4;

		switch ($this->type) {
			case DNS::DNS_TYPE_CNAME:
			case DNS::DNS_TYPE_NS:
			case DNS::DNS_TYPE_DS:
			case DNS::DNS_TYPE_SOA:
				$i = 0;

				while (($len=ord(substr($domain,$i++,1))) !== 0x00) {
					$this->labels->push(substr($buf,$i,$len));
					$i += $len;
				}

				break;

			case DNS::DNS_TYPE_OPT:
				// Domain is 0x00
				$this->ttl = Arr::get(unpack('N',substr($buf,$i,4)),1);
				$this->rddata_len = Arr::get(unpack('n',substr($buf,$i+4,2)),1);
				$this->rddata = substr($buf,$i+6,$this->rddata_len);

				break;

			default:
				dd(['unknown type:'.$this->type,'buf'=>$this->buf]);
		}
	}

	public function __get(string $key): mixed
	{
		switch ($key) {
			case 'length':
				return strlen($this->buf);

			default:
				throw new \Exception(sprintf('%s:Unknown key [%s]',self::LOGKEY,$key));
		}
	}

	public function __tostring(): string
	{
		return $this->buf;
	}
}