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

ADOBE CONFIDENTIAL
------------------
Copyright 2018 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 WFArguments = require 'WFArguments'
local WFPlatformInfo = require 'WFPlatformInfo'

local derefOpt = assert( KSTableUtils.derefOpt )


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

local check = assert( WFArguments.check )

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

local LrmPeopleIndexDefinitions = {}

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

function LrmPeopleIndexDefinitions.generateIndexSchema( indexStoreSchema )

	check( 'WFRxIndexStoreSchema' )

	--persons table

	local persons_sql
	local persons_hasOneRowPerDocument
	local persons_uselocalId

	if WFPlatformInfo.isiOS then
		persons_sql = [[CREATE TABLE persons( personId, name, hidden, primaryId, cover, thumbnail_url )]]
		persons_hasOneRowPerDocument = true
		persons_uselocalId = true
	else
		persons_sql = [[CREATE TABLE persons( name, thumnailLink, hidden, primaryId )]]
		persons_hasOneRowPerDocument = false
		persons_uselocalId = false
	end

	indexStoreSchema:addTable  {

		sql = persons_sql,
		hasOneRowPerDocument = persons_hasOneRowPerDocument,
		uselocalId = persons_uselocalId,

		updateLazily = false,
		
		relevantTypeSubtypeTuples = {
			{ 'asset', 'person' }
		},

		map = function( docValue, emit )

			if docValue._deleted then
				return
			end

			local thumbnail_href =  derefOpt( docValue, '_serverProvidedMetadata', 'links',
				'/rels/rendition_type/thumbnail2x', 'href' )


			local name = derefOpt( docValue, 'name' ) or ''
			local hidden = derefOpt( docValue, 'hidden' ) or false
			local primaryId = derefOpt( docValue, 'primary' ) or ''

			if WFPlatformInfo.isiOS then
				local personId = derefOpt( docValue, '_id' )
				local cover = derefOpt( docValue, 'cover', 'id' ) or ''
				emit( personId, name, hidden, primaryId, cover, thumbnail_href )

			else
				if not thumbnail_href then
					return
				end
				emit ( name, thumbnail_href, hidden, primaryId )
			end
		end
	}

	if WFPlatformInfo.isiOS then
		indexStoreSchema:addIndex [[CREATE INDEX persons_personId_name ON persons( personId, name, hidden, primaryId )]]
	else
		indexStoreSchema:addIndex [[CREATE INDEX person_primaryId ON persons( primaryId )]]
	end

    --person_assets table

	local faces_sql

	if WFPlatformInfo.isiOS then
		faces_sql = [[CREATE TABLE faces( faceId, assetId, personId, person_confirmed, x_axis, y_axis, width, height )]]
	else
		faces_sql = [[CREATE TABLE faces( assetId, personId, regionId, person_confirmed , x_axis , y_axis , width , height )]]
	end

    indexStoreSchema:addTable  {

        sql = faces_sql,

        useLocalId = true,
        hasOneRowPerDocument = false,

		relevantTypeSubtypeTuples = {
			{ 'asset', 'image' },
			{ 'asset', 'video' }
		},

        map = function(docValue, emit)

            if docValue._deleted then
                return
            end

            local regionList = derefOpt( docValue, 'xmp','mwg-rs', 'Regions', 'RegionList' )

            local ppl = {}
            for regionId, region in pairs( regionList or {} ) do

				if region.Type == "Face" then

                    local area = derefOpt( region, 'Area' )

                    local people = derefOpt( region, 'Extensions', 'adobe-fi', 'People')


                    for personId, person in pairs( people or {} ) do

						if WFPlatformInfo.isiOS then
							if not person.Rejected then
								emit( regionId, docValue._id, personId, person.Confirmed and true or false, area.x, area.y, area.w, area.h )
							end
						else
	                        if (not ppl[personId] and not person.Rejected) then
	                            ppl[personId] = true
	                            emit( docValue._id, personId, regionId, person.Confirmed and true or false ,area.x, area.y, area.w, area.h )
                        end
						end

                    end
                end
            end

        end
    }

	if WFPlatformInfo.isiOS then
		indexStoreSchema:addIndex [[CREATE INDEX faces_confirmed_asset_person ON faces( person_confirmed, assetId, personId )]]
	else
	    indexStoreSchema:addIndex [[CREATE INDEX faces_personId ON faces( personId )]]
		indexStoreSchema:addIndex [[CREATE INDEX faces_assetId ON faces( assetId )]]
	end

    --similar_persons table

	if not WFPlatformInfo.isiOS then

	    indexStoreSchema:addTable  {

	        sql = [[CREATE TABLE similar_person( personId, similarPersonId, confidence )]],
			
			relevantTypeSubtypeTuples = {
				{ 'asset', 'person' }
			},

	        map = function( docValue, emit )

	        if docValue.type == 'asset' and docValue.subtype == 'person' and not docValue._deleted then

	            local personId = derefOpt( docValue, '_id' )

	            local rejectedMap = derefOpt( docValue, 'rejected' ) or  {}

	            local links = derefOpt( docValue, '_serverProvidedMetadata', 'links' )

	            local start = "/rels/people/similar"

	            local len = string.len( start )

	            for k,v in pairs( links or {} ) do

	                if string.sub( k, 1, len ) == start  then

	                    local similarPersonId = v.id

	                    if not rejectedMap[similarPersonId] then

	                        local confidence = v.confidence

	                        if personId and similarPersonId and confidence and personId ~= similarPersonId then
	                            emit( personId, similarPersonId, confidence )
	                        end
	                    end
	                end
	            end
	        end

	     end,
	    }

	end

end

return LrmPeopleIndexDefinitions
