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

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.self_test
local WFAsyncTestCase = require 'WFAsyncTestCase'
local WFRxTestCase = require 'WFRxTestCase'

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

	-- WF.oz_client.sync_engine
local WFOzSyncConstants = require 'WFOzSyncConstants'

local WFPlatformInfo = require 'WFPlatformInfo'

	-- Lrmobile_models
local LrmCatalogTestHelper = require 'LrmCatalogTestHelper'	
local LrmAssetInfoModel = require 'LrmAssetInfoModel'
local LrmConfig = require 'LrmConfig'

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

local LrmAssetInfoModelTest = {}

local catalog

local TEST_TIMEOUT = 10

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

function LrmAssetInfoModelTest.setUp()

	catalog = LrmCatalogTestHelper.makeCatalogService()
	
end

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

function LrmAssetInfoModelTest.tearDown()

	if catalog then
		
		catalog:close()
		
	end
	
end

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

local function makeExpectedDoc( revisionId, hasThumbnailLocally, hasPreviewLocally, hasProxyLocally, hasMasterLocally  )

	return {
		revisionId = revisionId,
		binaryPreference = LrmConfig.StrategyPreferMaster,
		width = 1200,
		height = 1000,
		captureDate = '2004-11-09',
		fileName = 'Image01.jpg',
		croppedHeight = 150,
		croppedWidth = 150,
		xmpCameraRaw = '<xmp />',
		userOrientation = 2,
		canDevelop = false,
		hasThumbnailLocally = hasThumbnailLocally and true or false,
		hasPreviewLocally = hasPreviewLocally and true or false,
		hasMasterLocally = hasMasterLocally and true or false,
		hasProxyLocally = hasProxyLocally and true or false,
		hasMasterOnOz = false,
		originalIsValid = true,
		flag = 'pick',
		rating = 0,
		contentTypeNumber = 1000,
		isVideo = false,
		xmp = {
			copyright = 'Copyright',
			exposureTime = '100',
			flashFired = false,
			fnumber = '100.0',
			apertureValue = '100.0',
			focalLength = '100',
			isoSpeedRatings = '100',
			make = 'Make',
			model = 'Model',
			cameraMake = 'Make',
			cameraModel = 'Model',
			lens = 'Lens',
		}
	}
	
end

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

local function makeInitialDoc( userId )

	assert( userId, 'Expect userId' )
	
	return {
		subtype = 'image',
		captureDate = '2004-11-09',
		importSource = {
			fileName = 'Image01.jpg',
			originalWidth = 1200,
			originalHeight = 1000,
		},
		develop = {
			croppedHeight = 150,
			croppedWidth = 150,
			xmpCameraRaw = '<xmp />',
			userOrientation = 2,
		},
		xmp = {
			dc = {
				rights = 'Copyright',
			},
			exif = {
				ExposureTime = { 100, 1 },
				FNumber = { 100, 1 },
				ApertureValue = { 100, 1 },
				FocalLength = { 100, 1 },
				ISOSpeedRatings = 100,
			},
			tiff = {
				Make = 'Make',
				Model = 'Model',
			},
			aux = {
				Lens = 'Lens',
			}
		},
		reviews = {
			[ userId ] = {
				flag = 'pick',
			}
		},
		_localOnly = {
			localUrl = '/var/mobile/0001',
		}
	}

end

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

function LrmAssetInfoModelTest.testBasicAssetInfo( test )

	local assetId = KSIdGenerator.uuidInLowercaseHex()
	local revisionId
	local expectedDocValue
	
	WFAsyncTestCase( test, TEST_TIMEOUT )
	
		:waitFor( function()
		
			return catalog:ozUserIdP()
				:mapDataP_new( function( userId )
			
					return catalog:docStore():applyOverlayToDocumentP {
						docId = assetId,
						docType = 'asset',
						overlay = makeInitialDoc( userId )
					}
				
				end )
				:mapDataP_new( function( revId )
					revisionId = revId
					expectedDocValue = makeExpectedDoc( revId )
				end )
		end )
		
		:waitFor( function()
		
			return LrmAssetInfoModel.makeModel( catalog, assetId, LrmConfig.StrategyPreferMaster ).valueB

		end )
		
		:continueWhenValueMatches( expectedDocValue )
		
		:waitFor( function()
		
			local overlay

			if WFPlatformInfo.isiOS then
				overlay = {
					_localOnly = {
						files = {
							preview = {

							}
						}
					}
				}
			else
				overlay = {
					_localOnly = {
						preview = {
							
						}
					}
				}
			end

			return catalog:docStore():applyOverlayToDocumentP {
				docId = assetId,
				docType = 'asset',
				overlay = overlay
			}
			:mapDataP_new( function( revId )
				revisionId = revId
			end )
			
		end )
		
		:waitFor( function()
		
			return LrmAssetInfoModel.makeModel( catalog, assetId, LrmConfig.StrategyPreferMaster ).valueB
			
		end )
		
		:continueWhenValueMatchesFunction( function()
		
			return makeExpectedDoc( revisionId, false, true )
		
		end ) 
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
				docId = assetId,
				docType = 'asset',
				overlay = {
					develop = {
						xmpCameraRaw = { _delete = true },
					},
				}
			}
			:mapDataP_new( function( revId )
				revisionId = revId
			end )
			
			
		end )
		
		:waitFor( function()
		
			return LrmAssetInfoModel.makeModel( catalog, assetId, LrmConfig.StrategyPreferMaster ).valueB
			
		end )
		
		:continueWhenValueMatchesFunction( function()
		
			local doc = makeExpectedDoc( revisionId, false, true )
			doc.xmpCameraRaw = nil
			
			return doc
			
		end )
		
end

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

function LrmAssetInfoModelTest.testReviews( test )

	local assetId = KSIdGenerator.uuidInLowercaseHex()
	local revisionId
	local freemiumUserId = WFOzSyncConstants.kGlobalDocumentId
	
	WFAsyncTestCase( test, TEST_TIMEOUT )
	
		:waitFor( function()
		
			return catalog:ozUserIdP()
				:mapDataP_new( function( userId )
			
					return catalog:docStore():applyOverlayToDocumentP {
						docId = assetId,
						docType = 'asset',
						overlay = makeInitialDoc( userId ),
					}
					:mapDataP_new( function( revId )
						revisionId = revId
					end )
					
				end )
			
		end )
		
		:waitFor( function()
		
			return LrmAssetInfoModel.makeModel( catalog, assetId, LrmConfig.StrategyPreferMaster ).valueB
			
		end )
		
		:continueWhenValueMatchesFunction( function()
			
			return makeExpectedDoc( revisionId ) 
		
		end )
		
		:waitFor( function()
		
			return catalog:ozUserIdP()
				:mapDataP_new( function( userId )
			
					return catalog:docStore():applyOverlayToDocumentP {
						docId = assetId,
						docType = 'asset',
						overlay = {
							reviews = {
								[ userId ] = {
									flag = 'reject',
								},
								[ freemiumUserId ] = {
									flag = 'unflagged',
								},
							}
						}
					}
					:mapDataP_new( function( revId )
						revisionId = revId
					end )
				end )
			
		end )
		
		:waitFor( function()
		
			return LrmAssetInfoModel.makeModel( catalog, assetId, LrmConfig.StrategyPreferMaster ).valueB
			
		end )
		
		:continueWhenValueMatchesFunction( function()
		
			local doc = makeExpectedDoc( revisionId )
			doc.flag = 'reject'
			
			return doc
			
		end )
		
		:waitFor( function()
		
			return catalog:ozUserIdP()
				:mapDataP_new( function( userId )
				
				return catalog:docStore():applyOverlayToDocumentP {
					docId = assetId,
					docType = 'asset',
					overlay = {
						ratings = {
							[ userId ] = {
								rating = 5,
							},
							[ freemiumUserId ] = {
								rating = 3,
							},
						}
					}
				}
				:mapDataP_new( function( revId )
					revisionId = revId
				end )
				
			end )
			
		end )
		
		:waitFor( function()
		
			return LrmAssetInfoModel.makeModel( catalog, assetId, LrmConfig.StrategyPreferMaster ).valueB
			
		end )
		
		:continueWhenValueMatchesFunction( function()
		
			local doc = makeExpectedDoc( revisionId )
			doc.flag = 'reject'
			doc.rating = 5
			
			return doc
			
		end )

		:waitFor( function()
		
			return catalog:ozUserIdP()
				:mapDataP_new( function( userId )
			
					return catalog:docStore():applyOverlayToDocumentP {
						docId = assetId,
						docType = 'asset',
						overlay = {
							ratings = {
								[ userId ] = {
									rating = 2,
								}
							}
						}
					}
					:mapDataP_new( function( revId )
						revisionId = revId
					end )
					
				end )
			
		end )
		
		:waitFor( function()
		
			return LrmAssetInfoModel.makeModel( catalog, assetId, LrmConfig.StrategyPreferMaster ).valueB
			
		end )
		
		:continueWhenValueMatchesFunction( function()
		
			local doc = makeExpectedDoc( revisionId )
			doc.flag = 'reject'
			doc.rating = 2
			
			return doc
			
		end )
		
end

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

local function makeThumbnail2xOverlay( initialRevId )

	local overlay

	if WFPlatformInfo.isiOS then
		overlay = {
			_localOnly = {
				files = {
					thumbnail2x = {
						revId = initialRevId and initialRevId or KSIdGenerator.uuidInLowercaseHex()
					},
				}
			}
		}
	else
		overlay = {
			_localOnly = {
				thumbnail2x = {
					revId = initialRevId and initialRevId or KSIdGenerator.uuidInLowercaseHex()
				},
			}
		}
	end

	return overlay

end

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

function LrmAssetInfoModelTest.testCustomData( test )

	local assetId = KSIdGenerator.uuidInLowercaseHex()
	
	local initialRevId = KSIdGenerator.uuidInLowercaseHex()
	
	local revisionId
	
	WFAsyncTestCase( test, TEST_TIMEOUT )
	
		:waitFor( function()
		
			return catalog:ozUserIdP()
				:mapDataP_new( function( userId )
			
					local initialDoc = makeInitialDoc( userId )
					
					WFTableMerge.applyOverlay( initialDoc, makeThumbnail2xOverlay( initialRevId ) )

					WFTableMerge.applyOverlay( initialDoc, {
						_localOnly = {
							lrm_customData = {
								histogramData = {
									isValidForCurrentRevision = true,
									currentRevision = initialRevId,
									data = 'foo',
								},
								importData = {
									isValidForCurrentRevision = false,
									currentRevision = initialRevId,
									data = 'foo',
								}
							}
						}
					} )

					return catalog:docStore():applyOverlayToDocumentP {
						docId = assetId,
						docType = 'asset',
						overlay = initialDoc,
					}
					:mapDataP_new( function( revId )
						revisionId = revId
					end )
					
				end )
			
		end )
		
		:waitFor( function()
		
			return LrmAssetInfoModel.makeModel( catalog, assetId, LrmConfig.StrategyPreferMaster ).valueB
			
		end )
		
		:continueWhenValueMatchesFunction( function()
			local d = makeExpectedDoc( revisionId )
			
			d.hasThumbnailLocally = true
					
			local custom = {
				customFields = {
					histogramData = {
						isValidForCurrentRevision = true,
						currentRevision = initialRevId,
						data = 'foo',
					},
					importData = {
						isValidForCurrentRevision = false,
						currentRevision = initialRevId,
						data = 'foo',
					}
				}
			}
					
			local expected = WFTableMerge.applyOverlay( d, custom )
				
			return expected
	
		end )
		:waitFor( function()
		
			local overlay = makeThumbnail2xOverlay()
			
			return catalog:docStore():applyOverlayToDocumentP {
				docId = assetId,
				docType = 'asset',
				overlay = overlay
			}
			:mapDataP_new( function( revId )
				revisionId = revId
			end )
			
		end )
		
		:waitFor( function()
		
			return LrmAssetInfoModel.makeModel( catalog, assetId, LrmConfig.StrategyPreferMaster ).valueB
			
		end )
		
		:continueWhenValueMatchesFunction( function()
			
			local d = makeExpectedDoc( revisionId )
			
			d.hasThumbnailLocally = true

			d.customFields = {
				importData = {
					isValidForCurrentRevision = false,
					currentRevision = initialRevId,
					data = 'foo',
				}
			}
			
			return d
			
		end )
		
end

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

function LrmAssetInfoModelTest.testAssetInfoBehavior( test )

	local assetId = KSIdGenerator.uuidInLowercaseHex()
	
	local revisionId
	local model
	local assetInfoB
	
	WFAsyncTestCase( test, TEST_TIMEOUT )
	
		:waitFor( function()
		
			return catalog:ozUserIdP()
				:mapDataP_new( function( userId )
			
					return catalog:docStore():applyOverlayToDocumentP {
						docId = assetId,
						docType = 'asset',
						overlay = makeInitialDoc( userId )
					}
					:mapDataP_new( function( revId )
						revisionId = revId
					end )
				
			end )
			
		end )
		
		:waitFor( function()
		
			model = LrmAssetInfoModel.makeModel( catalog, assetId, LrmConfig.StrategyPreferMaster )
			
			return model.valueB
			
		end )
		
		:continueWhenValueMatchesFunction( function()
		
			return makeExpectedDoc( revisionId ) 
		
		end )
		
		:waitFor( function()
		
			assetInfoB = model.models.assetInfo( model, LrmConfig.StrategyPreferMaster ).valueB
			
			return assetInfoB
			
		end )
		
		:continueWhenValueMatchesFunction( function()
		
			return makeExpectedDoc( revisionId ) 
		
		end )
		
		:waitFor( function()
		
			return catalog:docStore():applyOverlayToDocumentP {
					docId = assetId,
					docType = 'asset',
					overlay = {
						importSource = {
							originalWidth = 42,
						}
					}
				}
				:mapDataP_new( function( revId )
					revisionId = revId
				end )
			
		end )
		
		:waitFor( function()
		
			return assetInfoB
			
		end )
		
		:continueWhenValueMatchesFunction( function()
		
			local d = makeExpectedDoc( revisionId )
			
			d.width = 42
			
			return d
			
		end )
		
end

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

function LrmAssetInfoModelTest.testRatingFromFreemium( test )

	local assetId = KSIdGenerator.uuidInLowercaseHex()
	
	local revisionId
	local expectedDocValue
	
	WFAsyncTestCase( test, TEST_TIMEOUT )
	
		:waitFor( function()
		
			return catalog:ozUserIdP()
				:mapDataP_new( function( userId )
			
					local docValue = makeInitialDoc( userId )
					docValue.reviews = nil
			
					WFTableMerge.applyOverlay( docValue, { 
						ratings = {
							[ WFOzSyncConstants.kGlobalDocumentId ] = {
								rating = 5,
							},
						},
						reviews = {
							[ WFOzSyncConstants.kGlobalDocumentId ] = {
								flag = 'rejected',
							},
						}
					} )
			
					return catalog:docStore():applyOverlayToDocumentP {
						docId = assetId,
						docType = 'asset',
						overlay = docValue,
					}
					:mapDataP_new( function( revId )
						revisionId = revId
						expectedDocValue = makeExpectedDoc( revisionId )
						expectedDocValue.rating = 5
						expectedDocValue.flag = 'rejected'
					end )
					
				end )
			
		end )
		
		:waitFor( function()
		
			return LrmAssetInfoModel.makeModel( catalog, assetId, LrmConfig.StrategyPreferMaster ).valueB
			
		end )
		
		:continueWhenValueMatches( expectedDocValue )
		
end

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

function LrmAssetInfoModelTest.testBadFormattedRating( test )

	local assetId = KSIdGenerator.uuidInLowercaseHex()
	local revisionId
	local expectedDocValue 
	
	WFAsyncTestCase( test, TEST_TIMEOUT )
	
		:waitFor( function()
		
			return catalog:ozUserIdP()
				:mapDataP_new( function( userId )
			
					local docValue = makeInitialDoc( userId )
					
					docValue.reviews = nil
			
					WFTableMerge.applyOverlay( docValue, { 
						ratings = {
							[ WFOzSyncConstants.kGlobalDocumentId ] = {
								_deleted = true
							},
						},
						reviews = {
							[ WFOzSyncConstants.kGlobalDocumentId ] = {
								_deleted = true
							},
						}
					} )
			
					return catalog:docStore():applyOverlayToDocumentP {
						docId = assetId,
						docType = 'asset',
						overlay = docValue,
					}
					:mapDataP_new( function( revId )
						revisionId = revId
						expectedDocValue = makeExpectedDoc( revisionId )
						expectedDocValue.rating = 0
					end )
					
				end )
			
		end )
		
		:waitFor( function()
		
			return LrmAssetInfoModel.makeModel( catalog, assetId, LrmConfig.StrategyPreferMaster ).valueB
			
		end )
		
		:continueWhenValueMatches( expectedDocValue )
		
end


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

return WFRxTestCase.wrapSuite( LrmAssetInfoModelTest )

