<?php

declare(strict_types=1);
namespace Tests\git2;
use git2\git;
use git2\git_buf;
use git2\git_error_code;
use git2\git_note;
use git2\git_note_iterator;
use git2\git_oid;

final class NoteTest extends GitTestCase
{

	public function testCommitCreate(): void
	{
		$dir = $this->mkdir('commit_create');
		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, 'foo', $tree);

		$this->assertOK(git::note_commit_create($commitOut, $blobOut, $repo, null, $sig, $sig, $id, 'bar', false));
		$this->assertInstanceOf(git_oid::class, $commitOut);
		$this->assertInstanceOf(git_oid::class, $blobOut);

		$this->assertOK(git::commit_lookup($commit, $repo, $commitOut));
		$this->assertOK(git::note_commit_read($note, $repo, $commit, $id));
		$this->assertInstanceOf(git_note::class, $note);
		$this->assertSame('bar', git::note_message($note));
		$this->assertSame('john.doe@example.com', git::note_author($note)->email);
		$this->assertSame('john.doe@example.com', git::note_committer($note)->email);
		$this->assertSame('ba0e162e1c47469e3fe4b393a8bf8c569f302116', git::oid_tostr_s(git::note_id($note)));

		$this->assertOK(git::note_commit_remove($rid, $repo, $commit, $sig, $sig, $id));
		$this->assertSame('985a26077c5be5e81e3a8bd2bed504071c9aaae6', git::oid_tostr_s($rid));
	}

	public function testCreate(): void
	{
		$dir = $this->mkdir('create');
		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, 'foo', $tree);

		$this->assertOK(git::note_create($nid, $repo, null, $sig, $sig, $id, 'bar', false));
		$this->assertInstanceOf(git_oid::class, $nid);

		$this->assertOK(git::note_read($note, $repo, null, $id));
		$this->assertInstanceOf(git_note::class, $note);
		$this->assertSame('bar', git::note_message($note));
		$this->assertSame('john.doe@example.com', git::note_author($note)->email);
		$this->assertSame('john.doe@example.com', git::note_committer($note)->email);
		$this->assertSame('ba0e162e1c47469e3fe4b393a8bf8c569f302116', git::oid_tostr_s(git::note_id($note)));

		$this->assertOK(git::note_remove($repo, null, $sig, $sig, $id));
	}

	public function testDefaultRef(): void
	{
		$dir = $this->mkdir('default_ref');
		git::repository_init($repo, $dir, false);
		$this->assertOK(git::note_default_ref($buf, $repo));
		$this->assertInstanceOf(git_buf::class, $buf);
		$this->assertSame('refs/notes/commits', (string) $buf);
	}

	public function testIterators(): void
	{
		$dir = $this->mkdir('iterators');
		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, 'foo', $tree);
		git::note_commit_create($commitOut, $blob_out, $repo, null, $sig, $sig, $id, 'bar', false);
		git::note_create($nid, $repo, null, $sig, $sig, $id, 'bar 2', false);

		$this->assertOK(git::commit_lookup($notesCommit, $repo, $commitOut));

		$this->assertOK(git::note_commit_iterator_new($cIterator, $notesCommit));
		$this->assertInstanceOf(git_note_iterator::class, $cIterator);
		$this->assertOK(git::note_next($nextId, $nextAnnotatedId, $cIterator));
		$this->assertSame('ba0e162e1c47469e3fe4b393a8bf8c569f302116', git::oid_tostr_s($nextId));
		$this->assertSame('fe61c43f34fcc3bd7e9bfaa4b7739bf2be5aa05b', git::oid_tostr_s($nextAnnotatedId));
		$this->assertSame(git_error_code::ITEROVER, git::note_next($nextId, $nextAnnotatedId, $cIterator));

		$this->assertOK(git::note_iterator_new($nIterator, $repo, null));
		$this->assertInstanceOf(git_note_iterator::class, $nIterator);
		$this->assertOK(git::note_next($nextId2, $nextAnnotatedId2, $nIterator));
		$this->assertSame('3edf8898bc4ccd08513b7c5832073b7862918fbd', git::oid_tostr_s($nextId2));
		$this->assertSame('fe61c43f34fcc3bd7e9bfaa4b7739bf2be5aa05b', git::oid_tostr_s($nextAnnotatedId2));
		$this->assertSame(git_error_code::ITEROVER, git::note_next($nextId2, $nextAnnotatedId2, $nIterator));
	}

	public function testForeach(): void
	{
		$dir = $this->mkdir('foreach');
		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, 'foo', $tree);
		git::note_create($nid, $repo, null, $sig, $sig, $id, 'bar 2', false);

		$oids = [];

		$this->assertOK(git::note_foreach($repo, null, function (git_oid $blob_id, git_oid $annotated_object_id) use(&$oids): void {
			$oids[] = [git::oid_tostr_s($blob_id), git::oid_tostr_s($annotated_object_id)];
		}));

		$this->assertSame([['3edf8898bc4ccd08513b7c5832073b7862918fbd', 'fe61c43f34fcc3bd7e9bfaa4b7739bf2be5aa05b']], $oids);
	}

}