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

ADOBE CONFIDENTIAL
------------------
Copyright 2015 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.rxlua
local WFRxTestCase = require 'WFRxTestCase'

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

	-- WF.managed_catalog
local WFCatAssetTestUtils = require 'WFCatAssetTestUtils'
local WFCatAlbumTestUtils = require 'WFCatAlbumTestUtils'
local WFCatVersions = require 'WFCatVersions'
local WFCatMockCatalog = require 'WFCatMockCatalog'

	-- Lrmobile_models
local LrmLibraryAssetOrganizationModelImp = require 'LrmLibraryAssetOrganizationModelImp'

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

local LrmLibraryAssetOrganizationTest = {}

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

local catalogOptions = {
	indexDefinitions = 'LrmCatalogIndexDefinitions.lua'
}

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

function LrmLibraryAssetOrganizationTest.rxTestHasAssetsInAlbum( rxTest )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest, nil, nil, catalogOptions )

	local parentModelMock = {
		catalog = wfCatalog
	}

	local assetIds = rxTest:getFirstValue( WFCatAssetTestUtils.insertAssets( rxTest, wfCatalog, 3 ) )

	local albumId = KSIdGenerator.uuidInLowercaseHex()

	rxTest:waitFor( wfCatalog:docStore():applyOverlay( {
		type = 'album',
		_id = albumId,
		name = 'Test album',
	} ) )

	local albumAsset1 = WFCatAlbumTestUtils.createAlbumAsset( rxTest, albumId, assetIds[ 1 ] )

	rxTest:waitFor( wfCatalog:docStore():applyOverlay( albumAsset1 ) )

	local hasAssetsInAlbum = LrmLibraryAssetOrganizationModelImp.hasAssetsInAlbum(
			parentModelMock, albumId, { assetIds[ 1 ] } ).value

	rxTest:expectSingleValue( hasAssetsInAlbum, {
		state = true,
		assetIds = {
			[ assetIds[ 1 ] ] = true
		}
	} )

	local albumAsset2 = WFCatAlbumTestUtils.createAlbumAsset( rxTest, albumId, assetIds[ 2 ] )

	rxTest:waitFor( wfCatalog:docStore():applyOverlay( albumAsset2 ) )

	hasAssetsInAlbum = LrmLibraryAssetOrganizationModelImp.hasAssetsInAlbum(
			parentModelMock, albumId, { assetIds[ 1 ], assetIds[ 2 ] } ).value

	rxTest:expectSingleValue( hasAssetsInAlbum, {
		state = true,
		assetIds = {
			[ assetIds[ 1 ] ] = true,
			[ assetIds[ 2 ] ] = true
		}
	} )

end

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

function LrmLibraryAssetOrganizationTest.rxTestHasAssetsByLocalUrl( rxTest )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest, nil, nil, catalogOptions )

	local parentModelMock = {
		catalog = wfCatalog
	}

	local assetIds = rxTest:getFirstValue( WFCatAssetTestUtils.insertAssets( rxTest, wfCatalog, 3 ) )

	rxTest:waitFor( wfCatalog:docStore():applyOverlay( {
		_id = assetIds[ 1 ],
		_localOnly = {
			localUrl = 'local_url_of_asset1',
		},
	} ) )

	rxTest:waitFor( wfCatalog:docStore():applyOverlay( {
		_id = assetIds[ 3 ],
		_localOnly = {
			localUrl = 'url',
		},
	} ) )

	local hasAssetsByLocalUrl = LrmLibraryAssetOrganizationModelImp.hasAssetsByLocalUrl(
			parentModelMock, { 'url', 'another_url', 'a_third_url', 'local_url_of_asset1' } ).value
		:take( 1 )

	rxTest:expectSingleValue( hasAssetsByLocalUrl, {
			local_url_of_asset1 = assetIds[ 1 ],
			url = assetIds[ 3 ]
	} )

end

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

function LrmLibraryAssetOrganizationTest.rxTestEditedUneditedAssetsByLocalUrl( rxTest )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest, nil, nil, catalogOptions )

	local parentModelMock = {
		catalog = wfCatalog
	}

	local options = { noDevelopUserUpdated = true, noDevelopDevice = true }
	local assetIds = rxTest:getFirstValue( WFCatAssetTestUtils.insertAssets( rxTest, wfCatalog, 3, options ) )

	rxTest:waitFor( wfCatalog:docStore():applyOverlay( {
		_id = assetIds[ 1 ],
		_localOnly = {
			localUrl = 'local_url_of_asset1',
		},
		develop = {
			userUpdated = '2012-01-18T11:12:15'
		}
	} ) )

	rxTest:waitFor( wfCatalog:docStore():applyOverlay( {
		_id = assetIds[ 3 ],
		_localOnly = {
			localUrl = 'local_url_of_asset3',
		},
	} ) )

	local hasAssetsByLocalUrl = LrmLibraryAssetOrganizationModelImp.editedUneditedAssetsByLocalUrl(
		parentModelMock, { 'local_url_of_asset1', 'url', 'another_url', 'local_url_of_asset3' } ).value
		:take( 1 )

	rxTest:expectSingleValue( hasAssetsByLocalUrl, {
		edited = { local_url_of_asset1 = assetIds[ 1 ]},
		unedited = { local_url_of_asset3 = assetIds[ 3 ]}
	} )

end

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

function LrmLibraryAssetOrganizationTest.rxTestHasAssetsBySha256( rxTest )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest, nil, nil, catalogOptions )

	local parentModelMock = {
		catalog = wfCatalog
	}

	local assetIds = rxTest:getFirstValue( WFCatAssetTestUtils.insertAssets( rxTest, wfCatalog, 3 ) )

	local asset1Sha256 = 'asset-1-sha256'
	rxTest:waitFor( wfCatalog:docStore():applyOverlay( {
		_id = assetIds[ 1 ],
		importSource= {
			sha256 = asset1Sha256,
		},
	} ) )

	local asset3Sha256 = 'asset-3-sha256'
	rxTest:waitFor( wfCatalog:docStore():applyOverlay( {
		_id = assetIds[ 3 ],
		importSource= {
			sha256 = asset3Sha256,
		},
	} ) )

	local hasAssetsBySha256 = LrmLibraryAssetOrganizationModelImp.hasAssetsBySha256(
			parentModelMock, { asset1Sha256, 'asset-2-sha256', asset3Sha256 } ).value
		:take( 1 )

	rxTest:expectSingleValue( hasAssetsBySha256, {
			[asset1Sha256] = assetIds[ 1 ],
			[asset3Sha256] = assetIds[ 3 ]
	} )

end

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

function LrmLibraryAssetOrganizationTest.rxTestHasVersionAssetsByLinkedLocationSha256( rxTest )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest, nil, nil, catalogOptions )

	local parentModelMock = {
		catalog = wfCatalog
	}

	-- INSERT VERSIONS
	local assetIds = rxTest:getFirstValue( WFCatAssetTestUtils.insertAssets( rxTest, wfCatalog, 3 ) )

	local linkedLocationId1 = 'URI-1'
	local linkedLocationId2 = 'URI-2'
	local linkedLocationId3 = 'URI-3'

	local linkedLocation1
	local linkedLocation2
	local linkedLocation3

	local linkedLocationSource = 'apple.icloud'
	if WFPlatformInfo.isAndroid then
		linkedLocationSource = 'android.content'
	end

	linkedLocation1 = {
			id = linkedLocationId1,
			source = linkedLocationSource
		}

	linkedLocation2 = {
			id = linkedLocationId2,
			source = linkedLocationSource
		}

	linkedLocation3 = {
			id = linkedLocationId3,
			source = linkedLocationSource
		}


	-- Setup asset - implicit import, no export
	rxTest:waitFor( wfCatalog:docStore():applyOverlay( {
		_id = assetIds[ 1 ],
		importSource = { linkedLocation = linkedLocation1 },
	} ) )

	local asset1Doc = rxTest:getFirstValue( wfCatalog:docStore():docValue( assetIds[1] ) )

	local version1Sha256 = KSTableUtils.derefOpt(asset1Doc, 'importSource', 'sha256')

	-- Setup asset - implicit import
	-- Ensure that asset 2 has a linkedLocation and NO version
	rxTest:waitFor( wfCatalog:docStore():applyOverlay( {
		_id = assetIds[ 2 ],
		importSource = { linkedLocation = linkedLocation2 },

	} ) )

	-- Setup asset - implicit import
	rxTest:waitFor( wfCatalog:docStore():applyOverlay( {
		_id = assetIds[ 3 ],
		importSource = { linkedLocation = linkedLocation3 },

	} ) )

	local exportedId = 'i-am-exported'
	local exportedSha256 = 'i-am-a-new-sha-256'

	-- Export this version
	local exportLinkedLocation = {
		id = exportedId,
		source = linkedLocationSource,
		sha256 = exportedSha256
	}
	local versionId3 = rxTest:getFirstValue( WFCatVersions.createVersionForAsset(wfCatalog, assetIds[ 3 ], false, 'Unknown',  exportLinkedLocation) )


	local hasAssetsByLinkedLocationId = LrmLibraryAssetOrganizationModelImp.hasVersionAssetsByLinkedLocationSha256(
		parentModelMock, { exportedSha256, version1Sha256, 'a fake sha' } ).value


	rxTest:expectSingleValue( hasAssetsByLinkedLocationId, {
				[exportedSha256] = {
					assetId		 = assetIds[ 3 ],
					versionId	 = versionId3,
					linkedLocationId = exportedId,
					source		 = linkedLocationSource
				}
		} )

end

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

function LrmLibraryAssetOrganizationTest.rxTestHasAssetsByLinkedLocationId( rxTest )

	local wfCatalog = WFCatMockCatalog.createFakeWFCatalog( rxTest, nil, nil, catalogOptions )

	local parentModelMock = {
		catalog = wfCatalog
	}

	-- INSERT VERSIONS
	local assetIds = rxTest:getFirstValue( WFCatAssetTestUtils.insertAssets( rxTest, wfCatalog, 3 ) )

	local linkedLocationId1 = 'URI-1'
	local linkedLocationId2 = 'URI-2'
	local linkedLocationId3 = 'URI-3'

	local linkedLocation1
	local linkedLocation2
	local linkedLocation3

	local linkedLocationSource = 'apple.icloud'
	if WFPlatformInfo.isAndroid then
		linkedLocationSource = 'android.content'
	end

	linkedLocation1 = {
			id = linkedLocationId1,
			source = linkedLocationSource
		}

	linkedLocation2 = {
			id = linkedLocationId2,
			source = linkedLocationSource
		}

	linkedLocation3 = {
			id = linkedLocationId3,
			source = linkedLocationSource
		}


	-- Setup asset - implicit import, no export
	rxTest:waitFor( wfCatalog:docStore():applyOverlay( {
		_id = assetIds[ 1 ],
		importSource = { linkedLocation = linkedLocation1 },
	} ) )

	local asset1Doc = rxTest:getFirstValue( wfCatalog:docStore():docValue( assetIds[1] ) )

	local versionId1 = rxTest:getFirstValue( WFCatVersions.createVersionForAsset(wfCatalog, assetIds[ 1 ], false, 'Unknown' ) )
	
	-- Setup asset - implicit import
	-- Ensure that asset 2 has a linkedLocation and NO version
	rxTest:waitFor( wfCatalog:docStore():applyOverlay( {
		_id = assetIds[ 2 ],
		importSource = { linkedLocation = linkedLocation2 },

	} ) )

	local asset2Doc = rxTest:getFirstValue( wfCatalog:docStore():docValue( assetIds[2] ) )

	-- Setup asset - implicit import
	rxTest:waitFor( wfCatalog:docStore():applyOverlay( {
		_id = assetIds[ 3 ],
		importSource = { linkedLocation = linkedLocation3 },

	} ) )
	local asset3Doc = rxTest:getFirstValue( wfCatalog:docStore():docValue( assetIds[3] ) )

	local exportedId = 'i-am-exported'
	local exportedSha256 = 'i-am-a-new-sha-256'

	-- Export this version
	local exportLinkedLocation = {
		id = exportedId,
		source = linkedLocationSource,
		sha256 = exportedSha256
	}
	local versionId3 = rxTest:getFirstValue( WFCatVersions.createVersionForAsset(wfCatalog, assetIds[ 3 ], false, 'Unknown',  exportLinkedLocation) )


	local hasAssetsByLinkedLocationId = LrmLibraryAssetOrganizationModelImp.hasAssetsByLinkedLocationId(
		parentModelMock, { linkedLocationId1, linkedLocationId2, 'another_url', 'a_third_url', linkedLocationId3, exportedId } ).value

	local maybeSha256 = function(assetDoc)
		if WFPlatformInfo.isAndroid then
			return KSTableUtils.derefOpt(assetDoc, 'importSource', 'sha256')
                end
	end

	rxTest:expectSingleValue( hasAssetsByLinkedLocationId, {
			versions = {
				[exportedId] = {
					assetId		= assetIds[ 3 ],
					versionId	= versionId3,
					sha256		= WFPlatformInfo.isAndroid and exportedSha256 or nil,
					source		= linkedLocationSource
				}
			},
			assets = {
				[linkedLocationId1] = {
					assetId		= assetIds[ 1 ],
					sha256		= maybeSha256(asset1Doc),
					source		= linkedLocationSource
				},
				[linkedLocationId2] = {
					assetId		= assetIds[ 2 ],
					sha256		= maybeSha256( asset2Doc ),
					source		= linkedLocationSource
				},
				[linkedLocationId3] = {
					assetId		= assetIds[ 3 ],
					sha256		= maybeSha256( asset3Doc ),
					source		= linkedLocationSource
				}
			}
	} )

end

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

return WFRxTestCase.wrapSuite( 'LrmLibraryAssetOrganizationTest',  LrmLibraryAssetOrganizationTest )
