/*
 * Copyright © 2020-2026 Pierrick Caillon <pierrick.caillon+zipdirfs@megami.fr>
 */
#include "NativeChanged.h"
#include "../Utilities/Fixtures/FileSystem.h"
#include "test/gtest.h"
#include <filesystem>
#include <gtest/gtest.h>

namespace Test::ZipDirFs::Components
{
	namespace fs = std::filesystem;

	using ::Test::ZipDirFs::Utilities::Fixtures::FileSystem;
	using ::testing::_;
	using ::testing::ByRef;
	using ::testing::Eq;
	using ::testing::Return;
	using ::ZipDirFs::Components::NativeChanged;

	TEST(NativeChangedTest, Init)
	{
		FileSystem fs;
		const std::filesystem::path p(
			std::filesystem::path("path") / std::to_string(::Test::rand(UINT32_MAX)));
		EXPECT_CALL(fs, last_write_time(Eq(ByRef(p))))
			.WillOnce(Return(::Test::to_file_time(0)));
		NativeChanged dc(p);
		ASSERT_FALSE(dc());
	}

	TEST(NativeChangedTest, Same)
	{
		FileSystem fs;
		const std::filesystem::path p(
			std::filesystem::path("path") / std::to_string(::Test::rand(UINT32_MAX)));
		std::time_t origin(::Test::rand(UINT32_MAX));
		EXPECT_CALL(fs, last_write_time(Eq(ByRef(p))))
			.Times(2).WillRepeatedly(Return(::Test::to_file_time(origin)));
		NativeChanged dc(p);
		ASSERT_TRUE(dc());
		ASSERT_FALSE(dc());
	}

	TEST(NativeChangedTest, Futur)
	{
		FileSystem fs;
		const std::filesystem::path p(
			std::filesystem::path("path") / std::to_string(::Test::rand(UINT32_MAX)));
		std::time_t origin(::Test::rand(UINT32_MAX));
		std::time_t futur(::Test::rand(UINT32_MAX));
		while (origin == futur)
		{
			futur = ::Test::rand(UINT32_MAX);
		}
		if (origin > futur)
		{
			std::swap(origin, futur);
		}
		EXPECT_CALL(fs, last_write_time(Eq(ByRef(p))))
			.WillOnce(Return(::Test::to_file_time(futur)));
		NativeChanged dc(p);
		reinterpret_cast<NativeChangedAccess*>(&dc)->set_lastChanged(::Test::to_file_time(origin));
		ASSERT_TRUE(dc());
	}

	TEST(NativeChangedTest, Past)
	{
		FileSystem fs;
		const std::filesystem::path p(
			std::filesystem::path("path") / std::to_string(::Test::rand(UINT32_MAX)));
		std::time_t origin(::Test::rand(UINT32_MAX));
		std::time_t past(::Test::rand(UINT32_MAX));
		while (origin == past)
		{
			past = ::Test::rand(UINT32_MAX);
		}
		if (origin < past)
		{
			std::swap(origin, past);
		}
		EXPECT_CALL(fs, last_write_time(Eq(ByRef(p))))
			.WillOnce(Return(::Test::to_file_time(past)));
		NativeChanged dc(p);
		reinterpret_cast<NativeChangedAccess*>(&dc)->set_lastChanged(::Test::to_file_time(origin));
		ASSERT_TRUE(dc());
	}

	TEST(NativeChangedTest, Get)
	{
		std::time_t expected(::Test::rand(UINT32_MAX));
		NativeChanged dc("");
		const auto expected_time = ::Test::to_file_time(expected);
		reinterpret_cast<NativeChangedAccess*>(&dc)->set_lastChanged(expected_time);
		ASSERT_EQ(NativeChanged::FileTime{dc}, expected_time);
	}

	TEST(NativeChangedTest, GetTime)
	{
		FileSystem fs;
		std::time_t expected(::Test::rand(UINT32_MAX));
		const std::filesystem::path p(
			std::filesystem::path("path") / std::to_string(::Test::rand(UINT32_MAX)));
		EXPECT_CALL(fs, last_write_time(Eq(ByRef(p))))
			.WillOnce(Return(::Test::to_file_time(expected)));
		EXPECT_EQ(std::time_t{NativeChanged::getTime(p)}, expected);
	}
} // namespace Test::ZipDirFs::Components
