<?php

declare(strict_types=1);
namespace Tests\git2;
use git2\git;
use git2\Internal\Debug\Call;
use git2\Internal\FFI;
use FFI as NFFI;

final class FreeTest extends GitTestCase
{

	/** @var Call[] */
	private array $calls = [];

	protected function setUp(): void
	{
		parent::setUp();
		FFI::debug(fn(Call $call) => $this->calls[] = $call);
	}

	/**
	 * This is here just to confirm my assumption, which is that any _owner()
	 * function just returns pointer to an already allocated repository. This
	 * is probably obvious, but better be safe than sorry, right?
	 *
	 * If this wrapper is supposed to take care of the memory, which I believe
	 * it should, implementation needs to be done like this:
	 *
	 * 1) keep track of all handles that are assigned by reference without `const`,
	 * 2) automatically call appropriate _free() functions on them once they become subject to GC,
	 * 3) reference them by the relevant child objects, e. g. commit needs to point to the repository it belongs to,
	 * 4) obviously, re-use existing handles in all the _owner() functions and whatnot,
	 * 5) all this should be implemented within the Handle, not the public wrappers,
	 * 6) pray that PHP won't fuck me over through an incorrect destructor invocation order this time.
	 */
	public function testOwner(): void
	{
		$dir = $this->mkdir('owner');
		git::repository_init($repo, $dir, false);
		git::repository_index($index, $repo);
		git::index_write_tree($treeId, $index);
		git::tree_lookup($tree, $repo, $treeId);
		git::signature_new($sig, 'John Doe', 'john.doe@example.com', 1640263000, 60);

		git::commit_create_v(
			$id,
			$repo,
			'HEAD',
			$sig, $sig,
			null,
			'Hello world!',
			$tree,
		);

		git::commit_lookup($commit, $repo, $id);
		$owner = git::commit_owner($commit);
		$this->assertSame($owner, $repo);

		$repoAddr  = NFFI::cast('unsigned int', $owner->cdata->cdata)->cdata;
		$ownerAddr = NFFI::cast('unsigned int', $repo->cdata->cdata)->cdata;
		$this->assertSame($repoAddr, $ownerAddr);
	}

	public function testSimpleFree(): void
	{
		(function(): void {
			$dir = $this->mkdir('simple_free');
			git::repository_init($repo, $dir, false);
		})();

		$this->assertCount(2, $this->calls);
		$this->assertSame('git_repository_init', $this->calls[0]->function);
		$this->assertSame('git_repository_free', $this->calls[1]->function);
	}

}