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

WFRxIndexStoreSchemaVersionList.lua

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

ADOBE CONFIDENTIAL
------------------
Copyright 2020 Adobe
All Rights Reserved.

NOTICE: All information contained herein is, and remains
the property of Adobe and its suppliers, if any. The intellectual
and technical concepts contained herein are proprietary to Adobe
and its suppliers and are protected by all applicable intellectual
property laws, including trade secret and copyright laws.
Dissemination of this information or reproduction of this material
is strictly forbidden unless prior written permission is obtained
from Adobe.

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

	-- WF.core.utils
local WFArguments = require 'WFArguments'
local WFCapabilities = require 'WFCapabilities'
local WFPlatformInfo = require 'WFPlatformInfo'

local WFArguments_check = assert( WFArguments.check )

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

-- @mark WFRxIndexStoreSchemaVersionList namespace

local WFRxIndexStoreSchemaVersionList = {}

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

-- The indexStore schema version list definition.
-- sequence: a sequential list of schema versions. The version list based reindexer will
--           reindex all documents which are defined by sequences > the current sequence
--           If the current schema is not in list, fall back to hash based reindexing,
--           sequence = 0, if in this list, simply disables the fall back to hash based reindexing.
-- platforms: list of platforms affected by this sequence. 
--            allowed: iOS, Android, MacOSX, Windows and the composites Desktop, Mobile, All
--            Note: the lookup is case sensitive!
-- tables:    list of tables affected

-- Example:
--	{
--		{
--			sequence = 0,
--		},
--		{
--			sequence = 1,
--			platforms = { "Mobile", },
--			tables = { "coreInfo", "album", "album_asset" }
--		}
--	}

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


local indexStoreSchemaVersionList = {
	{
		sequence = 0, -- wf/releases/3.3
	},
	{
		sequence = 1,
		platforms = { "Desktop", },
		tables = { "asset_sync_status_ui", "assetPathsAndInfo", "presetsAndProfiles" }
		-- https://git.corp.adobe.com/lua/wf/pull/3290/commits/2cfc47bd4caf3b88c0d6d04a7db5ffe69a0b3ca5
		-- https://git.corp.adobe.com/lua/wf/pull/3290/commits/dc44a83f7f56d0e276505e4f0963e53b419215ae
	},
	{
		sequence = 2,
		platforms = { "Mobile", },
		tables = { "album_asset", "albums", "blocked_uploads", "cacheReferences", "profileRegistration", 
					"presetsProfiles", "trashAssets" }
		-- https://git.corp.adobe.com/lua/wf/pull/3290/commits/dc44a83f7f56d0e276505e4f0963e53b419215ae
	},
	{
		sequence = 3,
		platforms = { "Android", },
		tables = { "CustomCameraProfiles", "coreMD5" }
		-- https://git.corp.adobe.com/lua/wf/pull/3290/commits/dc44a83f7f56d0e276505e4f0963e53b419215ae
	},
	{
		sequence = 4,
		platforms = { "All", },
		tables = { "space_album" }
		-- https://git.corp.adobe.com/lua/wf/pull/3290/commits/dc44a83f7f56d0e276505e4f0963e53b419215ae
	},
	{
		sequence = 5,
		platforms = { "Desktop", },
		tables = { "cameras", "keywords", "locations" }
		-- https://git.corp.adobe.com/lua/wf/pull/3332/commits/0cdb2163bd6b84d140b751eb3b2c735c49caabe2
	},
	{
		sequence = 6,
		platforms = { "Desktop", },
		tables = { "asset_sync_status_ui" }
		-- https://git.corp.adobe.com/lua/wf/pull/3358/commits/9b5220328caddc5eb38e03bd13a674f6f25e2cb2
	},
	{
		sequence = 7,
		platforms = { "Mobile", },
		tables = { "coreInfo" }
		-- https://git.corp.adobe.com/lua/wf/pull/3358/commits/9b5220328caddc5eb38e03bd13a674f6f25e2cb2
	},
	{
		sequence = 8,
		platforms = { "All", },
		tables = { "needsBinaryUpload" }
		-- https://git.corp.adobe.com/lua/wf/pull/3379
	},
	{
		sequence = 9,
		platforms = { "Android", },
		tables = { "cacheReferences", "trashAssets" }
		-- https://git.corp.adobe.com/lua/wf/pull/3389
	},
	{
		sequence = 11,
		platforms = { "Desktop", },
		tables = { "simple_updates" }
		-- https://jira.corp.adobe.com/browse/WF-1730
	}
	
}

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

local validPlatforms = {
	iOS = true,
	Android = true,
	MacOSX = true,
	Windows = true,
	Desktop = true,
	Mobile = true,
	All = true,
}

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

local function sequenceAffectsThisPlatform( platforms )

	local platform = WFPlatformInfo.getOS()

	for _, v in ipairs( platforms ) do
	
		if validPlatforms[ v ] == nil then
			error( string.format( "WFRxIndexStoreSchemaVersionList: invalid platform specificer: %s", v ) )
		end

		if v == platform then
			return true
		end

		if WFPlatformInfo.isMobile() and v == "Mobile" then
			return true
		end

		if WFPlatformInfo.isDesktop and v == "Desktop" then
			return true
		end
		if v == "All" then
			return true
		end
	end

	return false
end

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

local function isInList( t, list )
	
	for _, v in ipairs( list ) do
		if v == t then 
			return true
		end
	end

	return false

end

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

local function addTables( tables, toBeReindexedTables, validTables )

	for _, t in ipairs( tables ) do

		if not isInList( t, validTables ) then
			error( string.format( "WFRxIndexStoreSchemaVersionList.addTables(): invalid table '%s' for this platform", t) )
		end

		if not isInList( t, toBeReindexedTables ) then
			toBeReindexedTables[ #toBeReindexedTables +1 ] = t
		end

	end

end

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

function WFRxIndexStoreSchemaVersionList.getTablesToReindex( currentSequence, validTables )

	WFArguments_check( '?number', 'table')

	if not currentSequence then
		currentSequence = -1
	end

	if WFPlatformInfo.isUnitTest() then
	
		-- Some index store unit tests use WFCapabilities to override the indexStoreSchemaVersionList
		-- defined in this file; this allows the tests to cover a wider array of reindexing scenarios.

		local WFMsgPack = require 'WFMsgPack'
		local WFCapabilities = require 'WFCapabilities'
		
		local maybeIndexStoreSchemaVersionListOverride = WFCapabilities.getCapability( 'WFRxIndexStoreTest.indexStoreSchemaVersionListOverride' )

		if maybeIndexStoreSchemaVersionListOverride then

			indexStoreSchemaVersionList = WFMsgPack.unpack( maybeIndexStoreSchemaVersionListOverride )

		else
		
			-- Default to an empty schema version list for unit tests.
			
			indexStoreSchemaVersionList = {
				{
					sequence = 0,
				}
			}
		
		end
		
	end

	if #indexStoreSchemaVersionList == 0 then
		error( "WFRxIndexStoreSchemaVersionList.getTablesToReindex(): invalid schema version list")
	end
	
	local lastSequence = -1
	
	local toBeReindexedTables = {}
	
	for _, v in ipairs( indexStoreSchemaVersionList ) do
		
		if type( v ) ~= 'table' then
			error( "WFRxIndexStoreSchemaVersionList.getTablesToReindex(): invalid schema version list, expected table" )
		end

		if type( v.sequence ) ~= 'number' or v.sequence <= lastSequence then
			error( "WFRxIndexStoreSchemaVersionList.getTablesToReindex(): invalid sequence" )
		end
		
		lastSequence = v.sequence
		
		if v.sequence > 0 then
		
			if type( v.platforms ) ~= 'table' or #v.platforms == 0 then
				error( "WFRxIndexStoreSchemaVersionList.getTablesToReindex(): invalid platforms" )
			end

			if type( v.tables) ~= 'table' or #v.tables == 0 then
				error( "WFRxIndexStoreSchemaVersionList.getTablesToReindex(): tables must be a list" )
			end

			if v.sequence > currentSequence then 
				if sequenceAffectsThisPlatform( v.platforms ) then
					addTables( v.tables, toBeReindexedTables, validTables )
				end
			end

		end

	end
		
	local baseSequence = indexStoreSchemaVersionList[ 1 ].sequence
	
	if currentSequence < 0 or
			( baseSequence > currentSequence and baseSequence ~= 0 ) or
			currentSequence > lastSequence then
	
		return lastSequence, "hashBasedIndexing"
			-- currentSequence is no longer in list, fall back to hash based reindexing
			-- OR currentSequence is newer than the latest entry in the list. fall back.
	
	else
	
		return lastSequence, toBeReindexedTables
		
	end

end

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

function WFRxIndexStoreSchemaVersionList.TEST_setSchemaVersionList( rxTest, schemaVersionList )

	WFArguments_check( 'table')
	
	local WFMsgPack = require 'WFMsgPack'
	
	WFCapabilities.setCapability( 'WFRxIndexStoreTest.indexStoreSchemaVersionListOverride', WFMsgPack.pack( schemaVersionList ) )

	rxTest:finally( function()
		WFCapabilities.setCapability( 'WFRxIndexStoreTest.indexStoreSchemaVersionListOverride', nil )
	end )

end

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

function WFRxIndexStoreSchemaVersionList.getSchemaVersionList()

	return indexStoreSchemaVersionList

end

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

return WFRxIndexStoreSchemaVersionList
