local myModule = require 'Module:Wikidata/Formatters/quantity'
local builder = require 'Module:Wikidata/build'
local ScribuntoUnit = require 'Module:ScribuntoUnit'
local suite = ScribuntoUnit:new()

function suite:testGetRawValue()
	for _, val in ipairs{ -1, 0, 0.5, 1 } do
		local value = builder.buildValueFromDatatype{
			datatype = 'quantity',
			value = val
		}
		self:assertEquals(val, myModule.getRawValue(value, {}))
	end
end

function suite:testGetRawValueConvertUnit()
	local provider = {
		{
			amount = 3,
			expected = 3000,
			tounit = 'Q11573', -- metre
			unit = 'Q828224' -- kilometre
		},
		{
			amount = 1000,
			expected = 1609344,
			tounit = 'Q11573', -- metre
			unit = 'Q253276' -- mile
		},
		{
			amount = 123,
			expected = 123,
			tounit = 'Q11573', -- metre
			unit = 'Q11570' -- kilogram
		},
		{
			amount = 1,
			expected = 1000000,
			tounit = 'Q174789', -- millimetre
			unit = 'Q828224' -- kilometre
		},
	}
	for _, data in ipairs(provider) do
		local value = builder.buildValueFromDatatype{
			datatype = 'quantity',
			value = data.amount,
			unit = data.unit,
		}
		local options = { unit = data.tounit }
		self:assertEquals(data.expected, myModule.getRawValue(value, options))
	end
end

function suite:testFormatRawValue()
	local provider = {
		{
			value = 1,
			expected = '1'
		},
		{
			value = 0,
			expected = '0'
		},
		{
			value = -1,
			expected = '−1'
		},
		{
			value = 1.5,
			expected = '1,5'
		},
		{
			value = 12345678,
			expected = '12 345 678'
		},
		{
			value = 1.234567,
			expected = '1,234 567'
		},
		{
			value = -1234.5678,
			expected = '−1 234,567 8'
		},
	}
	for _, data in ipairs(provider) do
		self:assertEquals(data.expected, myModule.formatRawValue(data.value, {}))
	end
end

function suite:testFormatValue()
	for _, val in ipairs{ -1, math.pi, 1234 } do
		local value = builder.buildValueFromDatatype{
			datatype = 'quantity',
			value = val,
		}
		self:assertEquals(
			myModule.formatRawValue(val, {}),
			myModule.formatValue(value, {})
		)
	end
end

function suite:testFormatValueWithMargin()
	for _, diff in ipairs{ 0, 1, 2.5, false } do
		local value = builder.buildValueFromDatatype{
			datatype = 'quantity',
			diff = diff or nil,
			value = 10,
		}
		if diff then
			self:assertEquals(
				'10±' .. myModule.formatRawValue(diff, {}),
				myModule.formatValue(value, { showmargin = true })
			)
		else
			self:assertEquals('10', myModule.formatValue(value, {}))
		end
	end
end

function suite:testFormatValueWithUnit()
	for _, unit in ipairs{ 'Q11573', 'Q11570', 'Q199', false } do
		local value = builder.buildValueFromDatatype{
			datatype = 'quantity',
			unit = unit or nil,
			value = 10,
		}
		local result = myModule.formatValue(value, {})
		if not unit or unit == 'Q199' then
			self:assertEquals('10', result)
		else
			self:assertStringContains('^10 %[%[', result)
			self:assertStringContains('%]%]$', result)
		end
	end
end

function suite:testFormatValueWithUnitConverted()
	local provider = {
		{
			amount = 3,
			convert = true,
			expected = 3000,
			tounit = 'Q11573', -- metre
			unit = 'Q828224' -- kilometre
		},
		{
			amount = 1000,
			convert = true,
			expected = 1609344,
			tounit = 'Q11573', -- metre
			unit = 'Q253276' -- mile
		},
		{
			amount = 123,
			convert = false,
			expected = 123,
			tounit = 'Q11573', -- metre
			unit = 'Q11570' -- kilogram
		},
	}
	for _, data in ipairs(provider) do
		local value = builder.buildValueFromDatatype{
			datatype = 'quantity',
			unit = data.unit,
			value = data.amount,
		}
		local result = myModule.formatValue(value, { unit = data.tounit })
		if data.convert then
			self:assertStringContains(
				myModule.formatRawValue(data.expected) .. ' [[' .. mw.wikibase.sitelink(data.tounit) .. '|',
				result,
				true
			)
		else
			self:assertStringContains(
				myModule.formatRawValue(data.amount) .. ' [[' .. mw.wikibase.sitelink(data.unit) .. '|',
				result,
				true
			)
		end
	end
end

function suite:testFormatValueSuppressUnit()
	for _, unit in ipairs{ 'Q11573', 'Q11570' } do
		local value = builder.buildValueFromDatatype{
			datatype = 'quantity',
			unit = unit,
			value = 1,
		}
		local result = myModule.formatValue(value, { showunit = false })
		self:assertNotStringContains('[[', result, true)
		self:assertNotStringContains(']]', result, true)
	end
end

return suite