<?php

namespace App\Classes;

use Illuminate\Http\UploadedFile;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\File\File as FileBase;

class File extends FileBase implements \Iterator
{
	private const LOGKEY = 'F--';
	private int $counter = 0;
	private bool $isArchive = FALSE;
	private bool $canHandle = FALSE;
	private \ZipArchive $z;
	private array $zipfile = [];

	public function __construct(mixed $path,bool $checkPath=true)
	{
		parent::__construct($path,$checkPath);

		switch($x=$this->guessExtension()) {
			case 'zip':
				$this->canHandle = TRUE;
				$this->isArchive = TRUE;
				$this->z = new \ZipArchive;
				$this->z->open($this->getRealPath());
				break;

			case NULL:
			case 'bin':
				if ($this->getExtension() == 'pkt' || ($path instanceof UploadedFile && $path->getClientOriginalExtension() == 'pkt')) {
					$this->canHandle = TRUE;
					break;
				};

			default:
				Log::alert(sprintf('%s:? Unknown file received: %s',self::LOGKEY,$x));
		}
	}

	/* ITERATOR */

	public function current()
	{
		if ($this->isArchive) {
			$this->zipfile = $this->z->statIndex($this->counter,\ZipArchive::FL_UNCHANGED);

			$f = $this->z->getStream($this->zipfile['name']);
			if (! $f)
				throw new \Exception(sprintf('%s:Failed getting ZipArchive::stream (%s)',self::LOGKEY,$this->z->getStatusString()));

			return $f;

		} else {
			return fopen($this->getRealPath(),'r+');
		}
	}

	public function next()
	{
		$this->counter++;
	}

	public function key()
	{
		return $this->counter;
	}

	public function valid()
	{
		// If we have a pkt file, then counter can only be 1.
		return $this->canHandle && (($this->isArchive && ($this->counter < $this->z->numFiles)) || $this->counter === 0);
	}

	public function rewind()
	{
		$this->counter = 0;
	}

	/* METHODS */

	public function itemName(): string
	{
		return ($this->isArchive && $this->valid()) ? Arr::get(stream_get_meta_data($this->current()),'uri') : $this->getFilename();
	}

	public function itemSize(): int
	{
		return $this->isArchive ? Arr::get($this->zipfile,'size') : $this->getSize();
	}
}