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

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.

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

-- Disable for LriOS as test relies on LrA style _localOnly structure.
-- LriOS uses C++ side TIBlobProvider for downloading binaries anyway

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

if WFPlatformInfo.isiOS then
       return {}
end

	-- RxLua
local Rx = require 'Rx'

	-- WF.core.reactive
local KSPromises = require 'KSPromises'

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

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

	-- WF.lrmobile
local LrmCatalogTestHelper = require 'LrmCatalogTestHelper'
local LrmOzBinaryDownloader = require 'LrmOzBinaryDownloader'
local LrmConfig = require 'LrmConfig'

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

-- @mark LrmOzBinaryDownloaderTest namespace

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

local LrmOzBinaryDownloaderTest = {}

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

local docStore, indexStore
local binaryDownloader
local catalog, renditionServer, OzProfileModule

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

function LrmOzBinaryDownloaderTest.setUp()

	docStore, indexStore = LrmCatalogTestHelper.makeInMemoryDatabases()
	
	catalog = {
		
		_indexStore = indexStore,
		_docStore = docStore,
		
		indexStore = function( self )
			return indexStore
		end,
		
		docStore = function( self )
			return docStore
		end,
		
		originalDataPathP = function( self, localAssetId )
			
			return docStore:applyOverlayToDocumentP {
				docType = 'asset',
				docId = localAssetId,
				overlay = {
					subtype = 'image',
					_localOnly = {
						originalFilePath = '/path/...',
					}
				}
			}
			
		end,
		
		proxyDataPathP = function( self, localAssetId, doNotFetch, size )
			
			return docStore:applyOverlayToDocumentP {
				docType = 'asset',
				docId = localAssetId,
				overlay = {
					subtype = 'image',
					_localOnly = {
						proxy = {
							filePath = '/path/...'
						}
					}
				}
			}
			
		end,
		
	}
	
	renditionServer = Rx.Class( 'WFOzRenditionServer', {
	
		downloadRenditionP = function( self, localAssetId, renditionName )
			
			return docStore:applyOverlayToDocumentP {
				docType = 'asset',
				docId = localAssetId,
				overlay = {
					subtype = 'image',
					_localOnly = {
						[ renditionName ] = {
							md5 = 'hash',
							revId = '16b97d9d9e3042d09633c3878622d48a',
						}
					}
				}
			}
			
		end,
		
	} )()
	
	OzProfileModule = {
	
		ensureProfilesExistLocallyP = function( catalog, assetId )
		
			return KSPromises.resolvedPromiseP( 'data', {} )
			
		end
	}
	
	local updateAcrProfileDatabase = Rx.Subject()
	local updateAcrPresetProfileDatabase = Rx.Subject()
	
	binaryDownloader = LrmOzBinaryDownloader {
							catalogService = catalog,
							renditionServer = Rx.Observable.just( renditionServer ),
							updateAcrProfileDatabase = updateAcrProfileDatabase,
							updateAcrPresetProfileDatabase = updateAcrPresetProfileDatabase,
							LrmOzProfileModule = OzProfileModule
						}
	
	binaryDownloader:stopDownloading()
	
end

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

function LrmOzBinaryDownloaderTest.tearDown()

	if docStore then
		docStore:close()
	end
	
	if indexStore then
		indexStore:close()
	end
	
	if binaryDownloader then
		binaryDownloader:close()
	end
	
end

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

function LrmOzBinaryDownloaderTest.testProxyOnlyDownload( test )

	local assetId = KSIdGenerator.uuidInLowercaseHex()
	local albumId = KSIdGenerator.uuidInLowercaseHex()
	local albumAssetId = KSIdGenerator.uuidInLowercaseHex()
	
	local queryB = indexStore:queryB { sql =
				[[	SELECT 
						renditionName 
					FROM 
						renditionRevisions 
					WHERE 
						renditionName IN ( 'thumbnail2x', 'preview', 'master', 'proxyWithoutMaster' ) 
					ORDER BY 
						renditionName]]
			}
			
	--------------------------------------------------------------------------------
			
	WFAsyncTestCase( test, 5 )
		
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
				docType = 'album',
				docId = albumId,
				overlay = {
					subtype = 'collection',
					name = 'test album',
				}
			}
			
		end )
		
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
				docType = 'album_asset',
				docId = albumAssetId,
				overlay = {
					album = {
						id = albumId,
					},
					asset = {
						id = assetId,
					}
				}
			}
			
		end )
		
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
				docType = 'asset',
				docId = assetId,
				overlay = {
					subtype = 'image',
					_serverProvidedMetadata = {
						links = {
							[ '/rels/rendition_type/thumbnail2x' ] = {
								href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/renditions/835c23790d534b28b8b7bb99740d13ba',
							},
							[ '/rels/rendition_type/2048' ] = {
								href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/renditions/835c23790d534b28b8b7bb99740d13ba',
							},
							[ '/rels/proxy_type/2560' ] = {
								href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/proxies/a5429e4c4bc7402bb8fb9102dbde4317'
							}
						},
					}
				},
			}
		
		end )
		
		:waitFor( queryB )
		
		:continueWhenValueMatches( {
			{
				'preview',
			},
			{
				'proxyWithoutMaster',
			},
			{
				'thumbnail2x',
			}
		} )
		
		:waitFor( function()
		
			binaryDownloader:startDownloading( LrmConfig.StrategyPreferProxy )
			
			return KSPromises.resolvedPromiseP( 'data', true )
			
		end )
		
		:continueWhenValueMatches( 'data', true )
		
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
				docType = 'album',
				docId = albumId,
				overlay = {
					subtype = 'collection',
					_localOnly = {
						useOffline = true,
					}
				}
			}
			
		end )
		
		:waitFor( queryB )
		
		:continueWhenValueMatches( {} )
	
end

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

function LrmOzBinaryDownloaderTest.testProxyPreferredDownload( test )

	local assetId = KSIdGenerator.uuidInLowercaseHex()
	local albumId = KSIdGenerator.uuidInLowercaseHex()
	local albumAssetId = KSIdGenerator.uuidInLowercaseHex()
	
	local queryB = indexStore:queryB { sql =
				[[	SELECT 
						renditionName 
					FROM 
						renditionRevisions 
					WHERE 
						renditionName IN ( 'thumbnail2x', 'preview', 'master', 'proxy' ) 
					ORDER BY 
						renditionName]]
			}
			
	--------------------------------------------------------------------------------
			
	WFAsyncTestCase( test, 5 )
		
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
				docType = 'album',
				docId = albumId,
				overlay = {
					subtype = 'collection',
					name = 'test album',
				}
			}
			
		end )
		
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
				docType = 'album_asset',
				docId = albumAssetId,
				overlay = {
					album = {
						id = albumId,
					},
					asset = {
						id = assetId,
					}
				}
			}
			
		end )
		
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
				docType = 'asset',
				docId = assetId,
				overlay = {
					subtype = 'image',
					_serverProvidedMetadata = {
						links = {
							[ '/rels/rendition_type/thumbnail2x' ] = {
								href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/renditions/835c23790d534b28b8b7bb99740d13ba',
							},
							[ '/rels/rendition_type/2048' ] = {
								href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/renditions/835c23790d534b28b8b7bb99740d13ba',
							},
							[ '/rels/proxy_type/2560' ] = {
								href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/proxies/a5429e4c4bc7402bb8fb9102dbde4317'
							},
							[ '/rels/master' ] = {
								href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/master'
							}
						},
					}
				},
			}
		
		end )
		
		:waitFor( queryB )
		
		:continueWhenValueMatches( {
			{
				'master',
			},
			{
				'preview',
			},
			{
				'proxy',
			},
			{
				'thumbnail2x',
			}
		} )
		
		:waitFor( function()
		
			binaryDownloader:startDownloading( LrmConfig.StrategyPreferProxy )
			
			return KSPromises.resolvedPromiseP( 'data', true )
			
		end )
		
		:continueWhenValueMatches( 'data', true )
		
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
				docType = 'album',
				docId = albumId,
				overlay = {
					subtype = 'collection',
					_localOnly = {
						useOffline = true,
					}
				}
			}
			
		end )
		
		:waitFor( queryB )
		
		:continueWhenValueMatches( {
			{
				'master',
			},
		} )
	
end

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

function LrmOzBinaryDownloaderTest.testMasterPreferredDownload( test )

	local assetId = KSIdGenerator.uuidInLowercaseHex()
	local albumId = KSIdGenerator.uuidInLowercaseHex()
	local albumAssetId = KSIdGenerator.uuidInLowercaseHex()
	
	local queryB = indexStore:queryB { sql =
				[[	SELECT 
						renditionName 
					FROM 
						renditionRevisions 
					WHERE 
						renditionName IN ( 'thumbnail2x', 'preview', 'master', 'proxyWithoutMaster' ) 
					ORDER BY 
						renditionName]]
			}
			
	--------------------------------------------------------------------------------
			
	WFAsyncTestCase( test, 5 )
		
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
				docType = 'album',
				docId = albumId,
				overlay = {
					subtype = 'collection',
					name = 'test album',
				}
			}
			
		end )
		
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
				docType = 'album_asset',
				docId = albumAssetId,
				overlay = {
					album = {
						id = albumId,
					},
					asset = {
						id = assetId,
					}
				}
			}
			
		end )
		
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
				docType = 'asset',
				docId = assetId,
				overlay = {
					subtype = 'image',
					_serverProvidedMetadata = {
						links = {
							[ '/rels/rendition_type/thumbnail2x' ] = {
								href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/renditions/835c23790d534b28b8b7bb99740d13ba',
							},
							[ '/rels/rendition_type/2048' ] = {
								href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/renditions/835c23790d534b28b8b7bb99740d13ba',
							},
							[ '/rels/proxy_type/2560' ] = {
								href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/proxies/a5429e4c4bc7402bb8fb9102dbde4317'
							},
							[ '/rels/master' ] = {
								href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/master'
							}
						},
					}
				},
			}
		
		end )
		
		:waitFor( queryB )
		
		:continueWhenValueMatches( {
			{
				'master',
			},
			{
				'preview',
			},
			{
				'thumbnail2x',
			}
		} )
		
		:waitFor( function()
		
			binaryDownloader:startDownloading( LrmConfig.StrategyPreferMaster )
			
			return KSPromises.resolvedPromiseP( 'data', true )
			
		end )
		
		:continueWhenValueMatches( 'data', true )
		
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
				docType = 'album',
				docId = albumId,
				overlay = {
					_localOnly = {
						useOffline = true,
					}
				}
			}
			
		end )
		
		:waitFor( queryB )
		
		-- :continueWhenValueMatches( {
		-- 	{
		-- 		'proxy',
		-- 	},
		-- } )

		-- TODO (jrechtie): dual negative loading: for now download proxy alongside with the master.
		-- To be reviewed after final decision about "Download for offline edit" behavior.
		:continueWhenValueMatches( {} )
	
end

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

function LrmOzBinaryDownloaderTest.testMasterPreferredWithProxyOnlyDownload( test )

	local assetId = KSIdGenerator.uuidInLowercaseHex()
	local albumId = KSIdGenerator.uuidInLowercaseHex()
	local albumAssetId = KSIdGenerator.uuidInLowercaseHex()
	
	local queryB = indexStore:queryB { sql =
				[[	SELECT 
						renditionName 
					FROM 
						renditionRevisions 
					WHERE 
						renditionName IN ( 'thumbnail2x', 'preview', 'master', 'proxyWithoutMaster', 'proxy' ) 
					ORDER BY 
						renditionName]]
			}
			
	--------------------------------------------------------------------------------
			
	WFAsyncTestCase( test, 5 )
		
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
				docType = 'album',
				docId = albumId,
				overlay = {
					subtype = 'collection',
					name = 'test album',
				}
			}
			
		end )
		
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
				docType = 'album_asset',
				docId = albumAssetId,
				overlay = {
					album = {
						id = albumId,
					},
					asset = {
						id = assetId,
					}
				}
			}
			
		end )
		
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
				docType = 'asset',
				docId = assetId,
				overlay = {
					subtype = 'image',
					_serverProvidedMetadata = {
						links = {
							[ '/rels/rendition_type/thumbnail2x' ] = {
								href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/renditions/835c23790d534b28b8b7bb99740d13ba',
							},
							[ '/rels/rendition_type/2048' ] = {
								href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/renditions/835c23790d534b28b8b7bb99740d13ba',
							},
							[ '/rels/proxy_type/2560' ] = {
								href = '/v1.0/catalogs/f50509f546184519afa38d4e55e442fc/assets/496e4bec7eff1bee558b4760ae00efa3/revisions/16b97d9d9e3042d09633c3878622d48a/proxies/a5429e4c4bc7402bb8fb9102dbde4317'
							},
						},
					}
				},
			}
		
		end )
		
		:waitFor( queryB )
		
		:continueWhenValueMatches( {
			{
				'preview',
			},
			{
				'proxy',
			},
			{
				'proxyWithoutMaster',
			},
			{
				'thumbnail2x',
			}
		} )
		
		:waitFor( function()
		
			binaryDownloader:startDownloading( LrmConfig.StrategyPreferMaster )
			
			return KSPromises.resolvedPromiseP( 'data', true )
			
		end )
		
		:continueWhenValueMatches( 'data', true )
		
		:waitFor( function()
			
			return docStore:applyOverlayToDocumentP {
				docType = 'album',
				docId = albumId,
				overlay = {
					subtype = 'collection',
					_localOnly = {
						useOffline = true,
					}
				}
			}
			
		end )
		
		:waitFor( queryB )
		
		:continueWhenValueMatches( {} )
	
end

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

return LrmOzBinaryDownloaderTest