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

WFUserFeedback.lua

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

ADOBE CONFIDENTIAL
___________________

Copyright 2022 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.

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

	-- Rx
local Rx = require 'Rx'
local Observable = Rx.Observable

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

	-- WF.core.logger
local WFLogger = require 'WFLogger'

local KSJsonEncoder = require 'KSJsonEncoder'
local KSDate = require "KSDate"
local KSIdGenerator = require 'KSIdGenerator'
local KSTableUtils = require "KSTableUtils"

local logger = WFLogger 'WFUserFeedback'

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

-- @mark WFUserFeedback namespace

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

local WFUserFeedback = {}

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

--[[!
	\brief Post user feedback for a specific image to Oz
	\param wfCatalog the catalog
	\param optAssetId the asset ID (Must be set if optAutoSavedVersionId is provided)
	\param optAutoSavedVersionId the ID of version to use
	\param rating -1, 0, +1 (negative, neutral, positive)
	\param feature which feature feedback is for
	\param categories which category was chosen for feedback
	\param optDescription user comments on the feature
	\param optFeedbackId feedbackId used for LrW post
	\param optDeviceInfo json device info based on webpage description
	\param optModelInfo the versions or unique ids for ML models used by this feature.
	\return (boolean) Return true if the post to Oz was successful
	
--]]

function WFUserFeedback.postUserFeedback( wfCatalog, optAssetId, optAutoSavedVersionId, rating, feature, categories, optDescription, optFeedbackId, optDeviceInfo, optModelInfo )

	WFArguments.check( 'WFCatalog', '?string|number', '?string', 'number', 'string', '?table', '?string', '?string', '?table', '?table' )

	if optAutoSavedVersionId then
		assert( optAssetId, "Asset ID must be provided when an auto-saved version ID is provided." )
	end

	local function getAppId()

		if WFPlatformInfo.getOS() == "iOS" then
			return "LriOS"
		elseif WFPlatformInfo.getOS() == "Android" then
			return "LrA"
		elseif WFPlatformInfo.getOS() == "MacOSX" or WFPlatformInfo.getOS() == "Windows" then
			return "LrD"
		end

		return "Unknown"

	end	

	local maybeDocValueStream = Observable.just( false )

	if optAssetId then
		maybeDocValueStream = wfCatalog:docStore():docValue( optAssetId )
	end

	return maybeDocValueStream

		:flatMap( function( maybeDocValue )

			local eventsUrl = "/v2/events/feedback"

			local httpArgs = {

				requestMethod = 'POST',
		
				requestHeaders = {
					{ 
						header = 'Content-Type', 
						value = 'application/json'
					},
				}

			}

			-- https://wiki.corp.adobe.com/pages/viewpage.action?spaceKey=lightroom&title=Bonanza+Message+Protocol+and+API
			local feedbackTable = {

				protocol_version = "1",
				id = KSIdGenerator.uuidInLowercaseHex(),
				ts = KSDate.timeInIso8601Format( nil, false ),
				created_by = wfCatalog:ozUserId(),
				feature = feature,
				feature_version = "1",
				permissions = { "all" },
				type = "simple",
				description = optDescription,

				-- new fields for LrD 5.5
				rating = rating,
				app_id = getAppId(),
				locale = WFLocalizationUtils.getLocaleId(),

			}

			if optFeedbackId then

				feedbackTable.feedback_id = optFeedbackId

			end   

			if categories and next( categories ) then

				feedbackTable.categories = categories

			end

			if optDeviceInfo then

				feedbackTable.device = optDeviceInfo

			end

			if optModelInfo then

				feedbackTable.models = optModelInfo

			end

			if optAutoSavedVersionId and maybeDocValue then

				local catalogId = wfCatalog:ozCatalogId()

				local targetURL = string.format( "/v2/catalogs/%s/assets/%s/versions/%s",
						catalogId, maybeDocValue._id, optAutoSavedVersionId )

				feedbackTable.targets = { 

					[ optAutoSavedVersionId ] = { 

						href = targetURL,
						upload_params = "true"

					}

				}

			end

			local jsonData = KSJsonEncoder.encodeOzUploadJson( feedbackTable )

			return wfCatalog:ozCatalogSpec():put( eventsUrl, jsonData, httpArgs )

				:map( function( responseJson, headers )

					local maybeStatusCode = KSTableUtils.derefOpt( headers, 'status_code' )

					if not headers or ( headers.status_code ~= '202' and headers.status_code ~= '404' ) then
					
						if maybeStatusCode == '403' then

							-- Oz will be sending back 403 for Edu and Enterprise K-12 user accounts which are not allowed to submit feedback.
							-- We want to silently handle this case for now until client side APIs and UI is set up to suppress
							-- K12 submission.
							-- https://jira.corp.adobe.com/browse/OZ-12108
							-- https://jira.corp.adobe.com/browse/NMB-25873
							
							logger:errorf( "Feedback cannot be posted for Edu and Enterprise K-12 accounts" )
							return false

						end

						error( "Fail to Post User feedback to event with HTTP status code %s", headers.status_code )

					end

					return true

				end )

		end )

end

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

return WFUserFeedback
