--[[----------------------------------------------------------------------------

ADOBE CONFIDENTIAL
------------------
Copyright 2022 Adobe
All Rights Reserved.

NOTICE: All information contained herein is, and remains
the property of Adobe and its suppliers, if any. The intellectual
and technical concepts contained herein are proprietary to Adobe
and its suppliers and are protected by all applicable intellectual
property laws, including trade secret and copyright laws.
Dissemination of this information or reproduction of this material
is strictly forbidden unless prior written permission is obtained
from Adobe.

------------------------------------------------------------------------------]]

	-- WF.core.self_test
local WFRxTestCase = require 'WFRxTestCase'

local WFTableDiff = require 'WFTableDiff'

--============================================================================--

local WFTableDiffTest = {}

--============================================================================--

function WFTableDiffTest.rxTestBasicDiff( rxTest )

	local function checkDiff( args )
		rxTest:expectEqual( args.expected, WFTableDiff.diff( args.T1, args.T2 ) )
	end

	-- noop case

	checkDiff({
		T1 = {},
		T2 = {},
		expected = {},
	})

	checkDiff({
		T1 = { a = 'a' },
		T2 = { a = 'a' },
		expected = {},
	})

	checkDiff({
		T1 = { a = {} },
		T2 = { a = {} },
		expected = {},
	})

	checkDiff({
		T1 = { a = { b = 'b' } },
		T2 = { a = { b = 'b' } },
		expected = {},
	})

	-- simple key deletion

	checkDiff({
		T1 = { foo = 1 },
		T2 = {},
		expected = {
			{key = "foo", kind = "deleted", path = "", depth = 0},
		},
	})

	checkDiff({
		T1 = { foo = 1, bar = 2 },
		T2 = { bar = 2 },
		expected = {
			{key = "foo", kind = "deleted", path = "", depth = 0},
		},
	})

	checkDiff({
		T1 = { foo = { subFoo = 1 }, bar = 2 },
		T2 = { bar = 2 },
		expected = {
			{key = "foo", kind = "deleted", path = "", depth = 0},
		},
	})

	-- simple key modification

	checkDiff({
		T1 = { foo = 1 },
		T2 = { foo = 2 },
		expected = {
			{ key = "foo", kind = "changed", value = 2, path = "", depth = 0}
		}
	})

	-- simple key addition

	checkDiff({
		T1 = { foo = 1 },
		T2 = { foo = 1, bar = 2 },
		expected = {
			{ key = "bar", kind = "added", value = 2, path = "", depth = 0}
		},
	})

	-- sub key modification

	checkDiff({
		T1 = { foo = { subFoo = 1 } },
		T2 = { foo = { subFoo = 2 } },
		expected = {
			{ key = "subFoo", kind = "changed", value = 2, path = "foo", depth = 1}
		},
	})

	-- sub key deletion

	checkDiff({
		T1 = { foo = { bar = 1, baz = 2 } },
		T2 = { foo = { baz = 2 } },
		expected = {
			{ key = "bar", kind = "deleted", path = "foo", depth = 1}
		},
	})

	checkDiff({
		T1 = { foo = { bar = { biz = 1, boz = 3 }, baz = 2 } },
		T2 = { foo = { bar = { boz = 3 }, baz = 2 } },
		expected = {
			{ key = "biz", kind = "deleted", path = "foo.bar", depth = 2}
		},
	})

	-- sub key modification

	checkDiff({
		T1 = { foo = { bar = { biz = 1, boz = 3 }, baz = 2 } },
		T2 = { foo = { bar = { biz = 10, boz = 3 }, baz = 2 } },
		expected = {
			{ key = "biz", kind = "changed", value = 10, path = "foo.bar", depth = 2}
		},
	})

	-- sub key addition

	checkDiff({
		T1 = { foo = { bar = { boz = 3 }, baz = 2 } },
		T2 = { foo = { bar = { biz = 1, boz = 3 }, baz = 2 } },
		expected = {
			{ key = "biz", kind = "added", value = 1, path = "foo.bar", depth = 2}
		},
	})

	-- full example

	checkDiff({
		T1 = {
			user = {
				name = "TinTin",
				pet  = "Milou",
				BD = {
					title = "L'Etoile Mysterieuse",
					language = {
						short = "FR"
					}
				},
			},
			},
		T2 = {
			user = {
				name = "Capitaine Haddock",
				BD = {
					title = "Il Temple del Sole",
					language = {
						long = "Italian"
					}
				},
			password = "******"
			},
			type = 'Character'
			},
		expected = {
			-- adds at level 0 come first
			{ key = "type", kind = "added", value = "Character", path = "", depth = 0 },

			-- then adds at level 1
			{ key = "password", kind = "added", value = "******", path = "user", depth = 1 },

			-- then changes at level 1
			{ key = "name", kind = "changed", value = "Capitaine Haddock", path = "user", depth = 1},

			-- then deletions at level 1
			{ key = "pet", kind = "deleted", path = "user", depth = 1 },

			-- then chages at level 2 (no adds or deletes to effect order)
			{ key = "title", kind = "changed", value = "Il Temple del Sole", path = "user.BD", depth = 2 },

			-- then adds at level 3
			{ key = "long", kind = "added", value = "Italian", path = "user.BD.language", depth = 3 },

			-- finally deletions at level 3
			{ key = "short", kind = "deleted", path = "user.BD.language", depth = 3 },

		},
	})

end

function WFTableDiffTest.rxTestPrettifyDiff( rxTest )

	local exampleDiff = {
			{ key = "foo", kind = "added", value = 5, path = "", depth = 0}
		}

	rxTest:expectEqual("ADDED Key: foo, Value: 5", WFTableDiff.prettifyDiff( exampleDiff ))

	exampleDiff = {
			{ key = "foo", kind = "added", value = 5, path = "", depth = 0},
			{ key = "bar", kind = "changed", value = "baz", path = "", depth = 0},
			{ key = "biz", kind = "deleted", path = "", depth = 0},
		}

	rxTest:expectEqual("ADDED Key: foo, Value: 5\nCHANGED Key: bar, Value: baz\nDELETED Key: biz", WFTableDiff.prettifyDiff( exampleDiff ))

	exampleDiff = {
		{ key = "biz", kind = "deleted", path = "foo.bar", depth = 2},
	}

	rxTest:expectEqual("DELETED Key: foo.bar.biz", WFTableDiff.prettifyDiff( exampleDiff ))

	exampleDiff = {
			{ key = "floop", kind = "changed", value = "flap", path = "", depth = 0},
			{ key = "baz", kind = "added", value = "BAZ", path = "foo.bar", depth = 2},
			{ key = "biz", kind = "deleted", path = "foo.bar", depth = 2},
		}

	local expectedString ="CHANGED Key: floop, Value: flap\nADDED Key: foo.bar.baz, Value: BAZ\nDELETED Key: foo.bar.biz"

	rxTest:expectEqual(expectedString, WFTableDiff.prettifyDiff( exampleDiff ))

end

return WFRxTestCase.wrapSuite( 'WFTableDiffTest', WFTableDiffTest )
