-- ROBLOX deviation: we do not have the BabelTraverse or Prettier types defined in the
-- types file

type SnapshotData = types.SnapshotData

type SnapshotStateOptions = {
	updateSnapshot: ConfigSnapshotUpdateState,
	-- ROBLOX deviation: the function return is defined as any instead of null | Prettier
	-- prettierPath: ConfigPath;
	expand: boolean?,
	snapshotFormat: PrettyFormatOptions,
}

type SnapshotMatchOptions = {
	testName: string,
	received: any?,
	key: string?,
	inlineSnapshot: string?,
	isInline: boolean,
	-- ROBLOX deviation: error type defined as any instead of Error
	error_: any,
}

type SnapshotReturnOptions = {
	actual: string,
	count: number,
	expected: string?,
	key: string,
	pass: boolean,
}

type SaveStatus = {
	deleted: boolean,
	saved: boolean,
}

type SnapshotState = {
	_counters: { [string]: number },
	_dirty: boolean,
	_index: number,
	_updateSnapshot: ConfigSnapshotUpdateState,
	_snapshotData: SnapshotData,
	_initialData: SnapshotData,
	_snapshotPath: ConfigPath,
	-- ROBLOX TODO: ADO-1552 align this type as Array<InlineSnapshot> when we support inlineSnapshot testing
	_inlineSnapshots: { any },
	-- ROBLOX deviation: defined as any for now because LuauPolyfill.Set<string> and Set.Set<string>
	-- both didn't seem to be working
	_uncheckedKeys: any,
	-- _uncheckedKeys: LuauPolyfill.Set<string>,
	-- ROBLOX deviation: omitting field _prettierPath
	-- _prettierPath: ConfigPath;
	_snapshotFormat: PrettyFormatOptions,

	added: number,
	expand: boolean,
	matched: number,
	unmatched: number,
	updated: number,

	_addSnapshot: (
		self: SnapshotState,
		key: string,
		receivedSerialized: string,
		options: { isInline: boolean, error: Error? }
	) -> (),
}

local SnapshotState = {}
SnapshotState.__index = SnapshotState

function SnapshotState.new(snapshotPath: ConfigPath, options: SnapshotStateOptions): SnapshotState
	local returnValue = getSnapshotData(snapshotPath, options.updateSnapshot)
	local data = returnValue.data
	local dirty = returnValue.dirty

	local self = {
		_snapshotPath = snapshotPath,
		_initialData = data,
		_snapshotData = data,
		_dirty = dirty,
		-- ROBLOX deviation: omitting assignment for getBabelTraverse, getPrettier
		_inlineSnapshots = {},
		_uncheckedKeys = Set.new(Object.keys(data)),
		_counters = {},
		_index = 0,
		expand = options.expand or false,
		added = 0,
		matched = 0,
		unmatched = 0,
		_updateSnapshot = options.updateSnapshot,
		updated = 0,
		_snapshotFormat = options.snapshotFormat,
	}

	return (setmetatable(self, SnapshotState) :: any) :: SnapshotState
end

function SnapshotState:markSnapshotsAsCheckedForTest(testName: string): ()
	for index, uncheckedKey in self._uncheckedKeys:ipairs() do
		if keyToTestName(uncheckedKey) == testName then
			self._uncheckedKeys:delete(uncheckedKey)
		end
	end
end
