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

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.

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

local WFRxRunUntilDone = require 'WFRxRunUntilDone'

local WFRxThrottledBatchedApplyOverlayToIds = require 'WFRxThrottledBatchedApplyOverlayToIds'

local WFLogger = require 'WFLogger'
local peopleLogger = WFLogger "LrmPeopleLogger"
-- :setLevel 'debug'

local LrmPeopleModel = {}

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

function LrmPeopleModel:getAllFaces()
    local sql =
    {
        sql = [[SELECT docId, name, thumnailLink, hidden, primaryId from persons]]
    }
    local queryResult = self.catalog:indexStore()

    :query ( sql )

    return{
        value = queryResult,
    }

end

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

function LrmPeopleModel:getPersonAssetCounts()
    local sql =
    {
		sql = [[SELECT ifnull(m.docId, p.docId) as fullDocId, count(distinct faces.assetId) as assetCount,
		c.name as person_name, c.hidden from faces join persons p on p.docId = faces.personId
		left join persons m on m.docId = p.primaryId
		join persons c on c.docId = fullDocId
		GROUP BY fullDocId
		HAVING (assetCount > 4 or c.name != '')
		ORDER BY person_name DESC]],

--        sql = [[ SELECT ifnull(m.docId, p.docId) as fullDocId,
--		count(distinct faces.assetId) as assetCount,
--		ifnull(ifnull(m.name, p.name), '') as person_name, ifnull(ifnull(m.hidden, p.hidden) , 0.0)
--		from faces join persons p on p.docId = faces.personId
--		left join persons m on m.docId = p.primaryId
--		GROUP BY fullDocId
--		HAVING (assetCount > 4 or ifnull(m.name, p.name) != '')
--		ORDER BY person_name DESC
--        ]],

		calm = 5
    }

	local queryResult = self.catalog:indexStore()

	:query ( sql )

	return{
		value = queryResult,
	}

end

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

function LrmPeopleModel:getFacesForAsset(assetId)
    local sql =
    {
        -- The default value of the primaryId is now a empty string (''), hence isNull will not work here
        -- sql = [[SELECT personId from faces WHERE assetId = ']] .. assetId .. [[']]
        sql = [[ SELECT distinct CASE WHEN p.primaryId = '' THEN p.docId ELSE p.primaryId END from persons p join faces f
        on f.personId = p.docId where f.assetId = ?
        ]],
        assetId
    }
    local queryResult = self.catalog:indexStore()

    :query ( sql )

    return{
        value = queryResult,
    }

end

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

function LrmPeopleModel:getSimilarFacesForPerson(personId)
	local sql =
	{
--        sql = [[SELECT sp.personId, ifnull(p.primaryId, p.docId) as similarPersonId, sp.confidence
--        from similar_person sp join persons p on p.docId = sp.personId WHERE sp.personId = ? ORDER BY sp.confidence DESC]],
		sql = [[ SELECT sp.personId, p.docId as similarPersonId, max(sp.confidence)
		from similar_person sp join persons p on p.docId = sp.similarpersonId WHERE sp.personId = ?
		AND (p.primaryId IS NULL or p.primaryId = '')
		GROUP BY similarPersonId
		ORDER BY sp.confidence DESC
		]],
		personId
	}
	local queryResult = self.catalog:indexStore()

	:query ( sql )

	return{
		value = queryResult,
	}

end

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

function LrmPeopleModel:updatePersonName(personId,name)

    local docIds = { personId }

    local result = self.catalog:indexStore():queryOnce {
        sql = [[SELECT docId from persons WHERE primaryId = ? ]],
		singleColumnQuery = true,
        personId
    }
    :flatMap( function ( data )
	
        for x,v in ipairs(data) do
            table.insert(docIds, v)
        end

		local overlay = {
			name = name
		}

		return WFRxThrottledBatchedApplyOverlayToIds( "updatePersonName", self.catalog:docStore(), overlay, docIds, 100, 10 )

    end )
    :call ( WFRxRunUntilDone )

    return {
        value = result
    }

end

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

function LrmPeopleModel:updateHiddenPerson(personId, hidden)

    local result = {}
    local overlay = {
        _id = personId,
        hidden = hidden
    }

    self.catalog:docStore():applyOverlay( overlay ):call ( WFRxRunUntilDone )

    return {
        value = result
    }

end

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

function LrmPeopleModel:updatePersonPrimaryId(personId, primary)

    local docIds = { personId }

    local result = self.catalog:indexStore():queryOnce {
        sql = [[SELECT docId from persons WHERE primaryId = ? ]] ,
        singleColumnQuery = true,
		personId
    }
    :flatMap( function ( data )
	
        for x,v in ipairs(data) do
            table.insert(docIds, v)
        end

		local overlay = {
			primary = primary
		}

		return WFRxThrottledBatchedApplyOverlayToIds( "updatePersonPrimaryId", self.catalog:docStore(), overlay, docIds, 100, 10 )

    end )
    :call ( WFRxRunUntilDone )

    return {
        value = result
    }

end

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

function LrmPeopleModel:updatePersonCoverId(personId, coverId)

    local result = {}
    local overlay = {
        _id = personId,
        coverId = coverId
    }

    self.catalog:docStore():applyOverlay( overlay ):call ( WFRxRunUntilDone )
    return{
        value = result
    }

end

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

function LrmPeopleModel:deletePersonName(personId)

    -- delete all secondary persons name as well

    local docIds = { personId }

    local result = self.catalog:indexStore():queryOnce {
        sql = [[SELECT docId from persons WHERE primaryId = ? ]] ,
        singleColumnQuery = true,
		personId
    }
    :flatMap( function ( data )

        for x,v in ipairs(data) do
            table.insert(docIds, v)
        end

		local overlay = {
			name = { _delete = true }
		}

		return WFRxThrottledBatchedApplyOverlayToIds( "deletePersonName", self.catalog:docStore(), overlay, docIds, 100, 10 )

    end )
    :call ( WFRxRunUntilDone )

    return {
        value = result
    }

end

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

function LrmPeopleModel:getRegionIdForFaceInAssets(personId , assetIds)

	local getRegionIdForFaceInAssetsSql =
			[[SELECT assetId, regionId, personId
				FROM faces 
				WHERE ( personId = ? OR personId IN ( SELECT docId from persons WHERE primaryId = ? ) )
					AND assetId IN CARRAY( ?, ?, 'char*' )]]

	local sql = {
		sql = getRegionIdForFaceInAssetsSql,
		personId,
		personId,
		assetIds,
		#assetIds
	}

	local queryResult = self.catalog:indexStore()
		:query( sql )

	return {
		value = queryResult,
	}

end

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

function LrmPeopleModel:setSuggestionRejected( personId, rejectedId )

    local result = {}
    local overlay = {
        _id = personId,
        rejected = {
            [rejectedId] = true
        }
    }

    self.catalog:docStore():applyOverlay( overlay ):call ( WFRxRunUntilDone )
	
    return{
        value = result
    }
	
end

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

local function bulkMoveAssetsToAnotherPerson(self,personIdTo,rows)

    local mwgrs = "mwg-rs"
    local adobefi = "adobe-fi"
    local rejected = "Rejected"
    local confirmed = "Confirmed"

    for i=1,#rows do
        local row = rows[i]
        peopleLogger:debugf("RegionId = %s assetId = %s PersonId = %s",row[1],row[2],row[3])
        local regionId = row[1]
        local assetId = row[2]
        local personId = row[3]
        local overlay = {

            _id = assetId,
            subtype = "image",
            type = "asset",

            xmp = {
                [ mwgrs ] = {
                    Regions = {
                        RegionList = {
                            [ regionId ] = {
                                Extensions = {
                                    [ adobefi ] = {
                                        People = {
                                            [personIdTo] = {
                                                [confirmed]  =  true,
                                                [rejected] = false
                                            },
                                            [personId] = {
                                                [rejected] = true,
                                                [confirmed]  =  false
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            },
        }


        self.catalog:docStore():applyOverlay( overlay ):call ( WFRxRunUntilDone )

    end
	
end

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

function LrmPeopleModel:moveAssetsToAnotherPerson(personIdTo,personIdFrom,assetIds)

	local moveAssetsToAnotherPersonSql =
			[[SELECT regionId, assetId, personId
				FROM faces 
				WHERE ( personId = ? OR personId IN ( SELECT docId from persons WHERE primaryId = ? ) )
					AND assetId IN CARRAY( ?, ?, 'char*' )]]

	local sql = {
		sql = moveAssetsToAnotherPersonSql,
		personIdFrom,
		personIdFrom,
		assetIds,
		#assetIds
	}

	peopleLogger:debugf( "SQL query  = %s", sql )

	local queryResult = self.catalog:indexStore()
		:queryOnce( sql )
		:tap( function( rows )
			peopleLogger:debugf("Rows  = %s",rows)
			bulkMoveAssetsToAnotherPerson(self,personIdTo,rows)
		end )

	return {
		value = queryResult,
	}

end

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

return LrmPeopleModel
