<?php

namespace Planaday\Utility\DataGrouping;

use ArrayAccess;
use ArrayIterator;
use Countable;
use IteratorAggregate;
use Traversable;

/**
 * @template K as int|string
 * @template V
 * @implements ArrayAccess<K, V>
 */
class LazyLoadingArray implements ArrayAccess, IteratorAggregate, Countable {
	protected array $container = [];
	protected ArrayIterator $iterator;

	/**
	 * @param K|null $offset
	 * @param V $value
	 *
	 * @return void
	 */
	public function offsetSet($offset, $value): void {
		if (is_null($offset)) {
			$this->container[] = $value;
		} else {
			$this->container[$offset] = $value;
		}
	}

	/**
	 * @param K $offset
	 *
	 * @return bool
	 */
	public function offsetExists($offset): bool {
		return isset($this->container[$offset]);
	}

	/**
	 * @param K $offset
	 *
	 * @return void
	 */
	public function offsetUnset($offset): void {
		unset($this->container[$offset]);
	}

	/**
	 * @param K $offset
	 *
	 * @return V|null
	 */
	public function offsetGet($offset): mixed {
		if (!isset($this->container[$offset])){
			return null;
		}

		if (is_callable($this->container[$offset])){
			$this->container[$offset] = $this->container[$offset]();
		}

		return $this->container[ $offset ];
	}

	public function getIterator(): Traversable {
		return new ArrayIterator($this->container);
	}

	public function count(): int {
		return count($this->container);
	}
}