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

LrmCacheIndexDefinitions.lua

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

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.utils
local KSTableUtils = require 'KSTableUtils'
local KSDate = require "KSDate"

local WFArguments = require 'WFArguments'

local WFPlatformInfo = require 'WFPlatformInfo'

local WFCatAssetUtils = require "WFCatAssetUtils"

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

local OzCatalogUploadStatus = require "OzCatalogUploadStatus"

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

local derefOpt = assert( KSTableUtils.derefOpt )

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

local derefUniversal = assert( WFCatAssetUtils.derefUniversal )

local WFCatAssetUtils_isValidOriginalOnOz = assert( WFCatAssetUtils.isValidOriginalOnOz, "WFCatAssetUtils.isValidOriginalOnOz was not found" )

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

local check = assert( WFArguments.check )

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

-- @mark LrmCacheIndexDefinitions namespace

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

local LrmCacheIndexDefinitions = {}

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

--[[
	These constants are only used when existing photos (imported on 2011-08-12
	and before are in the system and we didn't capture the rendition size.
]]--

local defaultSizeForRendition = {
	original = 20000000,
	proxy = 943718,
	preview = 150000,
	thumbnail = 12000,
	thumbnail2x = 48000,
	xmp_develop = 16384
}

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

local paths = {
	thumbnail = { 'files', 'renditions', 'thumbnail' },
	thumbnail2x = { 'files', 'renditions', 'thumbnail2x' },
	preview = { 'files', 'renditions', '2048' },
	proxy = { 'files', 'proxy', '2560' },
	original = { 'files', 'original', 'master' },
	xmp_develop = { 'files', 'xmp_develop' }
}

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

function LrmCacheIndexDefinitions.relativePathFromDocValue( docValue )
	
	local renditions = { 'thumbnail', 'thumbnail2x', 'preview', 'master' }
	local results = {}
	
	for _, rendition in ipairs( renditions ) do
	
		local path = paths[ rendition ]
		
		if path then
	
			local relativePath = derefUniversal( docValue, unpack( path ), 'relativePath' )
			results[ #results ] = relativePath
		
		end
	end

	
	return unpack ( results, 1, #results )

end

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

function LrmCacheIndexDefinitions.generateIndexSchema( indexStoreSchema )

	check( 'WFRxIndexStoreSchema' )

	-- table coreMD5
	
	if WFPlatformInfo.isAndroid then
	
		-- Android only
	
		indexStoreSchema:addTable  {
		
			sql = [[CREATE TABLE coreMD5( thumbnail, thumbnail2x, preview, master )]],
		
			relevantTypeSubtypeTuples = {
				{ 'asset', 'image' },
				{ 'asset', 'video' }
			},

			hasOneRowPerDocument = true,
		
			map = function( docValue, emit )
				
				if docValue.type == 'asset' and (docValue.subtype == 'image' or docValue.subtype == 'video') 
				  and not docValue._deleted then
		
					local thumbnail, thumbnail2x, preview, master = LrmCacheIndexDefinitions.relativePathFromDocValue( docValue )
					
					if thumbnail or thumbnail2x or preview or master then
						emit( thumbnail, thumbnail2x, preview, master )
					end
				
				end
					
			end,
		
		}
		
	end

	-- table cacheReferences

	local sql, map, relevantTypeSubtypeTuples

	if WFPlatformInfo.isAndroid then
		sql = [[CREATE TABLE cacheReferences( assetId, md5, renditionName, size, epoch, hasUploaded, isTrash )]]
	else
		sql = [[CREATE TABLE cacheReferences( assetId, path, renditionName, contentId, size, userUpdated, hasUploaded, isTrash )]]
	end		
	
	relevantTypeSubtypeTuples = {
		{ 'asset', 'image' },
		{ 'asset', 'deleted_image' },
		{ 'asset', 'video' },
		{ 'asset', 'deleted_video' },
		{ 'version', 'edit' }
	}

	map = function( docValue, emit )

		if docValue.type ~= 'asset' and docValue.type ~= 'version' then
			return
		end
		
		if docValue._deleted then
			return
		end
		
		local assetId

		if docValue.type == 'asset' then
			assetId = docValue._id
		else
			assetId = KSTableUtils.derefOpt( docValue, 'asset', 'id' )
		end
		
		local isTrash = ( docValue.subtype == 'deleted_image' or docValue.subtype == 'deleted_video' )
		
		local serverLinks =
			  ( docValue._serverProvidedMetadata
			and docValue._serverProvidedMetadata.links ) or {}

		local function emitForRenditionName( renditionName, ozNameForRendition )

			local function pathFor( renditionName, key )
			
				local path = KSTableUtils.deepCopy( paths[ renditionName ] )
				path[ #path + 1 ] = key
			
				return path
				
			end
		
			if not paths[ renditionName ] then
				return
			end
				
			local renditionKey = derefUniversal( docValue, unpack( pathFor( renditionName, 'relativePath' ) ) )
			if not renditionKey then
				return
			end
			
			local fileSize = derefUniversal( docValue, unpack( pathFor( renditionName, 'fileSize' ) ) )
			
			if renditionName == 'latestOriginal' or renditionName == 'original' then
				-- Temporary check to correct the local file path and replace
				-- 'Adobe Carousel Library.cr' with 'Adobe Revel Library.cr'
		
				-- FIXME [ngautam 2011-11-15] This should really be done via an upgrade process
				-- that updates the database with the correct file paths but this is not
				-- feasible in the current time frame.
				renditionKey = OzCatalogUploadStatus.checkAndCorrectLocalPath( renditionKey )
			end
			
			if renditionKey then
			
				local serverLinksForRendition = serverLinks[ ozNameForRendition ]
				local shouldUpload
				
				if ( renditionName ~= 'latestOriginal' and renditionName ~= 'proxy' ) then
				
					shouldUpload = ( not serverLinksForRendition )
						or serverLinksForRendition.invalid
						or ( renditionName == 'original' and not WFCatAssetUtils_isValidOriginalOnOz( docValue ) )
						
				else
					-- We don't upload the latest original
					shouldUpload = false
				end
					
				if WFPlatformInfo.isiOS then  

					local contentId = derefUniversal( docValue, unpack( pathFor( renditionName , 'contentId' ) ) )

					emit( assetId,
						  renditionKey,
						  renditionName,
						  contentId,
						  fileSize or defaultSizeForRendition[ renditionName ] or 1000000,
						  docValue.userUpdated or KSDate.timeInIso8601Format(),
						  shouldUpload and 0 or 1,
						  isTrash and 1 or 0 )
						
				else

					local epoch = derefOpt( docValue, '_localOnly', renditionName, 'epoch' )

					emit( assetId,
						  renditionKey,
						  renditionName,
						  fileSize or defaultSizeForRendition[ renditionName ] or 1000000,
						  epoch or 1,
						  shouldUpload and 0 or 1,
						  isTrash and 1 or 0 )
	
				end
			
			end
		
		end

		if docValue.type == 'asset' then
		
			emitForRenditionName( 'thumbnail', '/rels/rendition_type/144h' )
			emitForRenditionName( 'preview', '/rels/rendition_type/2048' )
			emitForRenditionName( 'proxy', '/rels/proxy_type/2560' )
			emitForRenditionName( 'original', '/rels/master' )
			emitForRenditionName( 'latestOriginal', '' )
			
		end
		
		-- Versions and Assets have xmp develop settings and thumbnails.
		emitForRenditionName( 'xmp_develop', '/rels/xmp/develop' )
		emitForRenditionName( 'thumbnail2x', '/rels/rendition_type/thumbnail2x' )
		
	end

	indexStoreSchema:addTable { sql=sql, map=map, relevantTypeSubtypeTuples=relevantTypeSubtypeTuples }

	if WFPlatformInfo.isAndroid then
		indexStoreSchema:addIndex [[CREATE INDEX cacheReferences_epoch ON cacheReferences( epoch DESC, size )]]
		indexStoreSchema:addIndex [[CREATE INDEX cacheReferences_md5 ON cacheReferences( md5 ASC, docId )]]
		indexStoreSchema:addIndex [[CREATE INDEX cacheReferences_potentialVictims
			ON cacheReferences( epoch ASC, size DESC, docId )]]
	else
		indexStoreSchema:addIndex [[CREATE INDEX cacheReferences_userUpdated ON cacheReferences( userUpdated DESC, size )]]
		indexStoreSchema:addIndex [[CREATE INDEX cacheReferences_potentialVictims
			ON cacheReferences( userUpdated DESC, size DESC, docId )]]
	end
	
	indexStoreSchema:addIndex [[CREATE INDEX cacheReferences_assetId ON cacheReferences( assetId )]]
	indexStoreSchema:addIndex [[CREATE INDEX cacheReferences_hasUploaded ON cacheReferences( hasUploaded )]]
	indexStoreSchema:addIndex [[CREATE INDEX cacheReferences_isTrash ON cacheReferences( isTrash )]]
	indexStoreSchema:addIndex [[CREATE INDEX cacheReferences_renditionName ON cacheReferences( renditionName )]]

	-- table avatarCacheReferences
	
	indexStoreSchema:addTable {

		sql = [[CREATE TABLE avatarCacheReferences( md5, avatarType, size, epoch )]],

		relevantTypeSubtypeTuples = {
			{ 'feedbackuser', 'NULL' }
		},

		map = function( docValue, emit )
		
			local docType = docValue.type
			
			if docType == 'feedbackuser' then
			
				local avatars = derefOpt( docValue, 'avatars' )
				
				local function emitForAvatarType( avatarType )
				
					local info = derefOpt( avatars, avatarType )
					
					if info then
						emit( info.md5, avatarType, info.size, info.epoch )
					end
					
				end
				
				emitForAvatarType( 'small' )
				emitForAvatarType( 'small2x' )
				emitForAvatarType( 'medium' )
				emitForAvatarType( 'medium2x' )
				emitForAvatarType( 'large' )
				emitForAvatarType( 'large2x' )
				
			end
			
		end
		
	}

end

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

LrmCacheIndexDefinitions.defaultSizeForRendition = defaultSizeForRendition

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

return LrmCacheIndexDefinitions
