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

ADOBE CONFIDENTIAL
------------------
Copyright 2016 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.

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

	-- WF.core.os
local WFPlatformInfo = require 'WFPlatformInfo'

if not WFPlatformInfo.isMobile() then
       return {}
end

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

	-- WF.core.utils
local KSIdGenerator = require 'KSIdGenerator'

	-- WF.core.os
local KSData = require 'KSData'

	-- WF.lrmobile
local LrmCatalogTestHelper = require 'LrmCatalogTestHelper'
local LrmLibraryCacheModelImp = require 'LrmLibraryCacheModelImp'

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

local LrmLibraryCacheModelImpTest = {}

local catalog

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

local function makeLocalOnly( testFilePath, testDataSize, epoch )

	local localOnly

	if WFPlatformInfo.isiOS then
		localOnly = {
			files = {
				master = {
					path = testFilePath,
					fileSize = testDataSize,
				}
			}
		}
	else
		localOnly = {
			originalFilePath = testFilePath,
			original = {
				epoch = epoch,
				size = testDataSize,
			}
		}
	end

	return localOnly

end

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

local function getExpectedPurgableCacheSizeForAlbum( expectedSize, albumId )
	
	local expectedData = expectedSize
	if WFPlatformInfo.isAndroid then
		expectedData = {
			size = expectedSize,
			albumId = albumId,		-- android expects albumid as it does not maintain state
		}
	end
	
	return expectedData
	
end

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

function LrmLibraryCacheModelImpTest.setUp()
	
	catalog = LrmCatalogTestHelper.makeCatalogService()
	
end

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

function LrmLibraryCacheModelImpTest.tearDown()
	
	catalog:close()
	
	catalog = nil
	
end

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

function LrmLibraryCacheModelImpTest.testpurgeableCacheSizeForAlbum( test )

	local assetId = KSIdGenerator.uuidInLowercaseHex()
	local assetId2 = KSIdGenerator.uuidInLowercaseHex()
	local albumId = KSIdGenerator.uuidInLowercaseHex()
	local albumAssetId = KSIdGenerator.uuidInLowercaseHex()
	local albumAssetId2 = KSIdGenerator.uuidInLowercaseHex()
	
	local testFilePath = '/path'
	local testFilePath2 = '/path2'
	
	local function writeTestData( filePath, optData )
	
		local testData = KSData.make( optData or 'foo' )
		
		local size = KSData.length( testData )
		testData:close()
	
		return size
		
	end
	
	local testDataSize = writeTestData( testFilePath )
	local testDataSize2 = writeTestData( testFilePath2, 'foobar' )
	
	WFAsyncTestCase( test )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'asset',
				docId = assetId,
				overlay = {
					subtype = 'image',
					importSource = {
						originalWidth = 100,
						originalHeight = 100,
					},
					_localOnly = makeLocalOnly( testFilePath, testDataSize, 1 ),
					_serverProvidedMetadata = {
						links = {
							[ '/rels/master' ] = {
								href = '/v1.0/123..'
							}
						}
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'asset',
				docId = assetId2,
				overlay = {
					subtype = 'image',
					importSource = {
						originalWidth = 100,
						originalHeight = 100,
					},
					_localOnly =  makeLocalOnly( testFilePath2, testDataSize2, 2 ),
					_serverProvidedMetadata = {
						links = {
							[ '/rels/master' ] = {
								href = '/v1.0/123..'
							}
						}
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album',
				docId = albumId,
				overlay = {
					subtype = 'collection',
					name = 'foo',
					_localOnly = {
						useOffline = true,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album_asset',
				docId = albumAssetId,
				overlay = {
					album = {
						id = albumId,
					},
					asset = {
						id = assetId,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album_asset',
				docId = albumAssetId2,
				overlay = {
					album = {
						id = albumId,
					},
					asset = {
						id = assetId2,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return LrmLibraryCacheModelImp.purgeableCacheSizeForAlbum( { catalog = catalog }, albumId ).value
			
		end )
		
		:continueWhenValueMatches( 'data', getExpectedPurgableCacheSizeForAlbum( 9, albumId ) )
	
end

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

function LrmLibraryCacheModelImpTest.testMultipleAlbumPurgeSize( test )

	local assetId = KSIdGenerator.uuidInLowercaseHex()
	local assetId2 = KSIdGenerator.uuidInLowercaseHex()
	local albumId = KSIdGenerator.uuidInLowercaseHex()
	local albumId2 = KSIdGenerator.uuidInLowercaseHex()
	local albumAssetId = KSIdGenerator.uuidInLowercaseHex()
	local albumAssetId2 = KSIdGenerator.uuidInLowercaseHex()
	local album2AssetId1 = KSIdGenerator.uuidInLowercaseHex()
	local album2AssetId2 = KSIdGenerator.uuidInLowercaseHex()
	
	local testFilePath = '/path'
	local testFilePath2 = '/path2'
	
	local function writeTestData( filePath, optData )
	
		local testData = KSData.make( optData or 'foo' )
		
		local size = KSData.length( testData )
		testData:close()
	
		return size
		
	end
	
	local testDataSize = writeTestData( testFilePath )
	local testDataSize2 = writeTestData( testFilePath2, 'foobar' )
	
	WFAsyncTestCase( test )
	
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'asset',
				docId = assetId,
				overlay = {
					subtype = 'image',
					importSource = {
						originalWidth = 100,
						originalHeight = 100,
					},
					_localOnly =  makeLocalOnly( testFilePath, testDataSize, 1 ),
					_serverProvidedMetadata = {
						links = {
							[ '/rels/master' ] = {
								href = '/v1.0/123..'
							}
						}
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'asset',
				docId = assetId2,
				overlay = {
					subtype = 'image',
					importSource = {
						originalWidth = 100,
						originalHeight = 100,
					},
					_localOnly =  makeLocalOnly( testFilePath2, testDataSize2, 3 ),
					_serverProvidedMetadata = {
						links = {
							[ '/rels/master' ] = {
								href = '/v1.0/123..'
							}
						}
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album',
				docId = albumId,
				overlay = {
					subtype = 'collection',
					name = 'foo',
					_localOnly = {
						useOffline = true,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album',
				docId = albumId2,
				overlay = {
					subtype = 'collection',
					name = 'foo 2',
					_localOnly = {
						useOffline = false,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album_asset',
				docId = albumAssetId,
				overlay = {
					album = {
						id = albumId,
					},
					asset = {
						id = assetId,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album_asset',
				docId = albumAssetId2,
				overlay = {
					album = {
						id = albumId,
					},
					asset = {
						id = assetId2,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album_asset',
				docId = album2AssetId1,
				overlay = {
					album = {
						id = albumId2,
					},
					asset = {
						id = assetId,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album_asset',
				docId = album2AssetId2,
				overlay = {
					album = {
						id = albumId2,
					},
					asset = {
						id = assetId2,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return LrmLibraryCacheModelImp.purgeableCacheSizeForAlbum( { catalog = catalog }, albumId2 ).value
			
		end )
		
		:continueWhenValueMatches( 'data', getExpectedPurgableCacheSizeForAlbum( 0, albumId2 ) )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album',
				docId = albumId,
				overlay = {
					subtype = 'collection',
					name = 'foo',
					_localOnly = {
						useOffline = false,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return LrmLibraryCacheModelImp.purgeableCacheSizeForAlbum( { catalog = catalog }, albumId2 ).value
			
		end )
		
		:continueWhenValueMatches( 'data', getExpectedPurgableCacheSizeForAlbum( 9, albumId2 ) )
		
end

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

function LrmLibraryCacheModelImpTest.testMultiAlbumMultiAssetPurgeSize( test )

	local assetId1 = KSIdGenerator.uuidInLowercaseHex()
	local assetId2 = KSIdGenerator.uuidInLowercaseHex()
	local assetId3 = KSIdGenerator.uuidInLowercaseHex()
	local assetId4 = KSIdGenerator.uuidInLowercaseHex()
	
	local albumId1 = KSIdGenerator.uuidInLowercaseHex()
	local albumId2 = KSIdGenerator.uuidInLowercaseHex()
	
	local album1Asset1Id1 = KSIdGenerator.uuidInLowercaseHex()
	local album1Asset2Id2 = KSIdGenerator.uuidInLowercaseHex()
	
	local album2Asset3Id1 = KSIdGenerator.uuidInLowercaseHex()
	local album2Asset4Id2 = KSIdGenerator.uuidInLowercaseHex()
	
	local testFilePath = '/path'
	local testFilePath2 = '/path2'
	
	local function writeTestData( filePath, optData )
	
		local testData = KSData.make( optData or 'foo' )
		
		local size = KSData.length( testData )
		testData:close()
	
		return size
		
	end
	
	local testDataSize = writeTestData( testFilePath )
	local testDataSize2 = writeTestData( testFilePath2, 'foobar' )
	
	WFAsyncTestCase( test )
	
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'asset',
				docId = assetId1,
				overlay = {
					subtype = 'image',
					importSource = {
						originalWidth = 100,
						originalHeight = 100,
					},
					_localOnly =  makeLocalOnly( testFilePath, testDataSize, 1 ),
					_serverProvidedMetadata = {
						links = {
							[ '/rels/master' ] = {
								href = '/v1.0/123..'
							}
						}
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'asset',
				docId = assetId2,
				overlay = {
					subtype = 'image',
					importSource = {
						originalWidth = 100,
						originalHeight = 100,
					},
					_localOnly =  makeLocalOnly( testFilePath2, testDataSize2, 2 ),
					_serverProvidedMetadata = {
						links = {
							[ '/rels/master' ] = {
								href = '/v1.0/123..'
							}
						}
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'asset',
				docId = assetId3,
				overlay = {
					subtype = 'image',
					importSource = {
						originalWidth = 100,
						originalHeight = 100,
					},
					_localOnly =  makeLocalOnly( testFilePath2, testDataSize2, 2 ),
					_serverProvidedMetadata = {
						links = {
							[ '/rels/master' ] = {
								href = '/v1.0/123..'
							}
						}
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'asset',
				docId = assetId4,
				overlay = {
					subtype = 'image',
					importSource = {
						originalWidth = 100,
						originalHeight = 100,
					},
					_localOnly =  makeLocalOnly( testFilePath2, testDataSize2, 2 ),
					_serverProvidedMetadata = {
						links = {
							[ '/rels/master' ] = {
								href = '/v1.0/123..'
							}
						}
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album',
				docId = albumId1,
				overlay = {
					subtype = 'collection',
					name = 'foo 1',
					_localOnly = {
						useOffline = true,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album',
				docId = albumId2,
				overlay = {
					subtype = 'collection',
					name = 'foo 2',
					_localOnly = {
						useOffline = false,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album_asset',
				docId = album1Asset1Id1,
				overlay = {
					album = {
						id = albumId1,
					},
					asset = {
						id = assetId1,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album_asset',
				docId = album1Asset2Id2,
				overlay = {
					album = {
						id = albumId1,
					},
					asset = {
						id = assetId2,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album_asset',
				docId = album2Asset3Id1,
				overlay = {
					album = {
						id = albumId2,
					},
					asset = {
						id = assetId3,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album_asset',
				docId = album2Asset4Id2,
				overlay = {
					album = {
						id = albumId2,
					},
					asset = {
						id = assetId4,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return LrmLibraryCacheModelImp.purgeableCacheSizeForAlbum( { catalog = catalog }, albumId1 ).value
			
		end )
		
		:continueWhenValueMatches( 'data', getExpectedPurgableCacheSizeForAlbum( 9, albumId1 ) )
		
		:waitFor( function()
		
			return LrmLibraryCacheModelImp.purgeableCacheSizeForAlbum( { catalog = catalog }, albumId2 ).value
			
		end )
		
		:continueWhenValueMatches( 'data', getExpectedPurgableCacheSizeForAlbum( 12, albumId2 ) )
		
end

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

-- @mark All Photos purgeable cache size

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

function LrmLibraryCacheModelImpTest.testAllPhotospurgeableCacheSize( test )

	local assetId = KSIdGenerator.uuidInLowercaseHex()
	local assetId2 = KSIdGenerator.uuidInLowercaseHex()
	local albumId = KSIdGenerator.uuidInLowercaseHex()
	local albumAssetId = KSIdGenerator.uuidInLowercaseHex()
	local albumAssetId2 = KSIdGenerator.uuidInLowercaseHex()
	
	local testFilePath = '/path'
	local testFilePath2 = '/path2'
	
	local function writeTestData( filePath, optData )
	
		local testData = KSData.make( optData or 'foo' )
		
		local size = KSData.length( testData )
		testData:close()
	
		return size
		
	end
	
	local testDataSize = writeTestData( testFilePath )
	local testDataSize2 = writeTestData( testFilePath2, 'foobar' )
	
	WFAsyncTestCase( test )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'asset',
				docId = assetId,
				overlay = {
					subtype = 'image',
					importSource = {
						originalWidth = 100,
						originalHeight = 100,
					},
					_localOnly =  makeLocalOnly( testFilePath, testDataSize, 1 ),
					_serverProvidedMetadata = {
						links = {
							[ '/rels/master' ] = {
								href = '/v1.0/123..'
							}
						}
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'asset',
				docId = assetId2,
				overlay = {
					subtype = 'image',
					importSource = {
						originalWidth = 100,
						originalHeight = 100,
					},
					_localOnly =  makeLocalOnly( testFilePath2, testDataSize2, 2 ),
					_serverProvidedMetadata = {
						links = {
							[ '/rels/master' ] = {
								href = '/v1.0/123..'
							}
						}
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album',
				docId = albumId,
				overlay = {
					subtype = 'collection',
					name = 'foo',
					_localOnly = {
						useOffline = true,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album_asset',
				docId = albumAssetId,
				overlay = {
					album = {
						id = albumId,
					},
					asset = {
						id = assetId,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album_asset',
				docId = albumAssetId2,
				overlay = {
					album = {
						id = albumId,
					},
					asset = {
						id = assetId2,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return LrmLibraryCacheModelImp.purgeableCacheSize( { catalog = catalog } ).value
			
		end )
		
		:continueWhenValueMatches( 'data', 0 )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
			
				docType = 'album',
				docId = albumId,
				overlay = {
					subtype = 'collection',
					name = 'foo',
					_localOnly = {
						useOffline = false,
					}
				}
			}
			
		end )
		
		:waitFor( function()
		
			return LrmLibraryCacheModelImp.purgeableCacheSize( { catalog = catalog } ).value
			
		end )
		
		:continueWhenValueMatches( 'data', 9 )
		
end

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

return LrmLibraryCacheModelImpTest

