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

KSCocoaToLuaDataEncoderTest.lua

--------------------------------------------------------------------------------

ADOBE CONFIDENTIAL
------------------
Copyright 2013 Adobe Systems Incorporated
All Rights Reserved.

NOTICE: All information contained herein is, and remain the property of
Adobe Systems Incorporated and its suppliers, if any. The intellectual and
technical concepts contained herein are proprietary to Adobe Systems
Incorporated and its suppliers and may be covered by U.S. and Foreign
Patents, patents in process, and are protected by trade secret or copyright
law.  Dissemination of this information or reproduction of this material is
strictly forbidden unless prior written permission is obtained from
Adobe Systems Incorporated.

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

local WFPlatformInfo = require 'WFPlatformInfo'

if _G.DISTRIBUTION or not WFPlatformInfo.isCocoa then
	return {
		testDistributionDisabled = function()
			debug.print( "KSCocoaToLuaDataEncoderTest.lua must be run in a non-distribution Cocoa build" ) 		end
	}
	
end

--------------------------------------------------------------------------------

local KSCocoaToLuaDataEncoderTestingHelper = require 'KSCocoaToLuaDataEncoderTestingHelper'

local KSCocoaToLuaDataEncoderTest = {}

--[[
	
	For reference, the Cocoa data being sent by KSCocoaToLuaDataEncoderTestingHelper:

	#1: STANDARD ARRAY
		
	NSString* obj1 = @"Hello";
	NSNumber* obj2 = [ NSNumber numberWithFloat: 3.14 ];
	NSNumber* obj3 = [ NSNumber numberWithBool: YES ];
	NSNull* obj4 = [ NSNull null ];
	NSString* obj5 = @"Foo";
	
	return [ NSArray arrayWithObjects: obj1, obj2, obj3, obj4, obj5, nil ];
	
	#2: STANDARD DICTIONARY
	
	NSString* obj1 =  [ NSArray array ];
	NSNumber* obj2 = [ NSNumber numberWithFloat: 3.14 ];
	NSNumber* obj3 = [ NSNumber numberWithBool: YES ];
	NSNull* obj4 = [ NSNull null ];
	NSString* obj5 = @"Foo";
	
	NSNumber* key1 = [ NSNumber numberWithInt: 42 ];
	NSNumber* key2 = [ NSNumber numberWithBool: YES ];
	NSString* key3 = @"key3";
	NSString* key4 = @"key4";
	NSArray* key5 = [ NSArray arrayWithObject: key3 ];
	
	return [ NSDictionary dictionaryWithObjectsAndKeys: obj1, key1, obj2, key2, obj3, key3, obj4, key4, obj5, key5, nil ];
	
]]

--------------------------------------------------------------------------------

local function safeFloatsEqual( a, b )
	return math.abs( a - b ) < .001
end

--------------------------------------------------------------------------------

local function testBasicTable( foo )

	assert( foo[ 1 ] == "Hello" )
	assert( type( foo[ 2 ] ) == 'number' and safeFloatsEqual( foo[ 2 ], 3.14 ) )
	assert( foo[ 3 ] == true )
	assert( foo[ 4 ] == nil )
	assert( foo[ 5 ] == "Foo" )
	assert( not foo[ 6 ] )
	
	-- Can't assert size because there's a hole, so just assert there's no 6th item

end

--------------------------------------------------------------------------------

local function testStandardDict( foo )
	
	local tableKey = { "key3" }
	
	local tableValue = {}
	
	local expected = {
		[ 42 ] = tableValue,
		[ true ] = 3.14,
		[ "key3" ] = true,
		[ "key4" ] = nil,
		[ tableKey ] = "Foo",
		[ "URL" ] = "http://adobe.com",
	}
	
	local numPairsFound = 0
	
	for k, v in pairs( foo ) do
		
		numPairsFound = numPairsFound + 1
		
		if type( k ) == 'table' then
			assert( require 'KSTableUtils'.deepEquals( k, tableKey ) )
			assert( v == expected[ tableKey ] )
		elseif type( v ) == 'table' then
			assert( require 'KSTableUtils'.deepEquals( v, tableValue ) )
			assert( tableValue == expected[ k ] )
		elseif type( v ) == 'number' then
			assert( safeFloatsEqual( expected[ k ], v ) )
		else
			assert( expected[ k ] == v )
		end
		
	end
	
	local numPairsExpected = 0
	
	for k, v in pairs( expected ) do
		numPairsExpected = numPairsExpected + 1
	end
	
	assert( numPairsFound == numPairsExpected )
	
end

--------------------------------------------------------------------------------

function KSCocoaToLuaDataEncoderTest.testNSArray()

	local foo = KSCocoaToLuaDataEncoderTestingHelper.pushBasicNSArray()
	testBasicTable( foo )

end

--------------------------------------------------------------------------------

function KSCocoaToLuaDataEncoderTest.testNSSet()

	local foo = KSCocoaToLuaDataEncoderTestingHelper.pushBasicNSSet()
	
	assert( foo[ "Hello" ] == true )
	assert( foo[ true ] == true )
	assert( foo[ false ] == true )
	assert( foo[ math.huge ] == true )
	assert( foo[ -10 ] == true )

	local count = 0
	for k, v in pairs( foo ) do
		if type( k ) == "number" and k > 3 and k < 4 then
			assert( safeFloatsEqual( k, 3.14 )	)
		end
		count = count + 1
	end
	
	assert( count == 6 )

end

--------------------------------------------------------------------------------

function KSCocoaToLuaDataEncoderTest.testNSArrayExpanded()

	local foo = { KSCocoaToLuaDataEncoderTestingHelper.pushBasicNSArrayExpandedOnState() }
	testBasicTable( foo )

end

--------------------------------------------------------------------------------

function KSCocoaToLuaDataEncoderTest.testNSDictionary()
	
	local foo = KSCocoaToLuaDataEncoderTestingHelper.pushBasicNSDictionary()
	
	testStandardDict( foo )
	
end

--------------------------------------------------------------------------------

function KSCocoaToLuaDataEncoderTest.testNSArrayWithNestedDictionary()
	
	local foo = KSCocoaToLuaDataEncoderTestingHelper.pushSimpleArrayWithNestedDict()
	
	assert( #foo == 3 )
	assert( foo[ 1 ] == "first" )
	testStandardDict( foo[ 2 ] )
	assert( foo[ 3 ] == "third" )
	
end

--------------------------------------------------------------------------------

function KSCocoaToLuaDataEncoderTest.testRecursionSafetyCheck()
	
	local success, error = pcall( KSCocoaToLuaDataEncoderTestingHelper.pushOverlyNestedDict )
	
	assert( not success )
	assert( error == "KSCococaToLuaDataEncoder does not support encoding recursive tables, or nested tables deeper than 100 levels" )
	
end

--------------------------------------------------------------------------------

function KSCocoaToLuaDataEncoderTest.testNumericTypes()
	
	local foo = { KSCocoaToLuaDataEncoderTestingHelper.pushNumericTypes() }
	
	assert( #foo == 4, "KSCocoaToLuaDataEncoderTestingHelper.pushNumericTypes provided wrong number of results" )
	assert( foo[ 1 ] == false, "First result is not false; was type " .. type( foo[ 1 ] ) .. " (" .. tostring( foo[ 1 ] ) .. ")" )
	assert( foo[ 2 ] == true )
	assert( foo[ 3 ] == 42 )
	assert( safeFloatsEqual( foo[ 4 ], -2.5 ) )

end

--------------------------------------------------------------------------------

function KSCocoaToLuaDataEncoderTest.testEmptyStructures()
	
	local foo = { KSCocoaToLuaDataEncoderTestingHelper.pushEmptyStructures() }
	
	assert( #foo == 2 )
	
	local emptyDict = foo[ 1 ]
	local emptyArr = foo[ 2 ]
	
	assert( type( emptyDict ) == 'table' )
	assert( type( emptyArr ) == 'table' )
	
	local foundItem = false
	
	for k, v in pairs( emptyDict ) do
		foundItem = true
	end
	
	for k, v in pairs( emptyArr ) do
		foundItem = true
	end
	
	assert( not foundItem )
	
end

--------------------------------------------------------------------------------

function KSCocoaToLuaDataEncoderTest.disabled_testEncodeInvalidType()
	-- [arahn 2014-07-29]: This tests makes sure you can't do certain things,
	-- such as push an arbitrary NSObject to lua via WFCocoaToLuaDataEncoder;
	-- However, elsewhere we developed technology that let's us push any
	-- NSObject to lua.  But the former did not utilize the latter.  I found
	-- myself in need of being able to push an NSURL, and was annoyed by the need
	-- to convert it to an NSString first.  So I enabled this API to just use
	-- the push-anything logic (search for wf_pushToLua: if you're curious).
	-- However, that means this test is invalidate.  And I have to wonder: Who
	-- was so concerned that this API not gain functionality that this negative
	-- test was written?  Or was it just done in a spate of 100% coverage enthusiasm?
	-- I'll assume the latter, and now that there are no NSObject types that don't work
	-- I guess I'll disable it.
	local success, error = pcall( KSCocoaToLuaDataEncoderTestingHelper.pushInvalidTypes )
	
	assert( not success )
	assert( error == "Unrecognized data type in KSCocoaToLuaDataEncoder" )
	
end

--------------------------------------------------------------------------------

return KSCocoaToLuaDataEncoderTest
