local json = require "cjson"
local request = require "luis.request"
require "socket" 
module(..., package.seeall)

local m_instanceOwner
function SetOwner (instanceOwner)
	m_instanceOwner = instanceOwner
end

local m_defaultAppVersion = "2022-10-01-preview"

local function MakeCompleteURI (uriBaseId, uri, ...)
	uriBaseId = uriBaseId or "APPS"
	return m_instanceOwner:MakeCompleteURI(m_defaultAppVersion, uriBaseId, uri, ...)
end

local function MakePagingParameters (params)
	local api = require "luis"
	return api.MakePagingParameters(params)
end

function LoadAllAppEntities (appId, versionId, paginated, vcc) 
	assert(appId)
	assert(versionId)

	local resource_name, subscription_key_1 = GetLanguageStudioAccount(vcc)

	local uri = MakeCompleteURI("APPS", appId .."/:export?api-version=".. m_defaultApiVersion .. "&format=Conversation&stringIndexType=Utf16CodeUnit")
	uri = uri:gsub("resourcename", resource_name)

	LogInfo("[LUIS_APPS40:LoadAllAppEntities] uri: %s", uri)

	local additionalHeaders = {
		["Ocp-Apim-Subscription-Key"] = subscription_key_1
	}

	local success, response, headers = request.Post(uri, {}, "application/json; charset=UTF-8", additionalHeaders)
	if not success then
		LogError("[LUIS_APPS40:LoadAllAppEntities] LoadAllAppEntities Error: '%s'", json.encode(response))
		return false, response
	end

	-- luego obtengo el location
	local operationLocation = headers["operation-location"] 

	LogInfo("[LUIS_ENTITIES_COMPOSITE:LoadAllAppEntities] operationLocation: %s", operationLocation)

	-- luego consulto N veces ese location

	local success = false
	local response = {}
	local retry = 0
	local TOTAL_RETRIES = 10
	local TIMEOUT_SEC = 3

	while retry < TOTAL_RETRIES do
		retry = retry + 1
		
		success, response = request.Get(operationLocation, additionalHeaders)

		local encodedResponse = table.concat(response)
		local parsedResponse = json.decode(encodedResponse)

		if not success then
			LogError("[LUIS_ENTITIES_COMPOSITE:LoadAllAppEntities] Error loading all APP COMPOSITE ENTITIES on appId '%s' versionId: '%s'. Error: '%s'", appId, versionId, json.encode(response))
			return false, response
		end

		if parsedResponse.status == "succeeded" then

			success, response = request.Get(parsedResponse.resultUrl, additionalHeaders)
			
			encodedResponse = table.concat(response)			
			response = json.decode(encodedResponse)

			local entities = response.assets.entities
			
			for i, entity in ipairs(entities) do
				entity.name = entity.category
				entity.typeId = entity.compositionSetting
			end
			
			response = json.encode(entities)

			break
		else
			LogInfo("[LUIS_ENTITIES_COMPOSITE:LoadAllAppEntities] Waiting %d seconds.", TIMEOUT_SEC)
			socket.sleep(TIMEOUT_SEC)
		end
	end

	LogInfo("[LUIS_ENTITIES_COMPOSITE:LoadAllAppEntities] response: %s", json.encode(response))

	return true, response
end

function GetAppEntity (appId, entityId, versionId)
	assert(appId)
	assert(entityId)
	assert(versionId)

	local uri = MakeCompleteURI("APPS", "%s/versions/%s/compositeentities/%s", appId, versionId, entityId)

	local success, response = request.Get(uri)
	if not success then
		LogError("[LUIS_ENTITIES_COMPOSITE:GetAppEntity] Error get APP COMPOSITE ENTITIES '%s' on appId '%s' versionId: '%s' Error: '%s'", entityId, appId, versionId, json.encode(response))
		return false, response
	end

	LogInfo("[LUIS_ENTITIES_COMPOSITE:GetAppEntity] Success get APP COMPOSITE ENTITIES '%s' on appId '%s' versionId: '%s'.", entityId, appId, versionId)

	local encodedEntity = table.concat(response)
	return true, encodedEntity
end

function CreateAppEntity (info)
	assert(type(info) == "table")
	assert(info.appId)
	assert(info.versionId)
	assert(info.entity)

	local uri = MakeCompleteURI("APPS", "%s/versions/%s/compositeentities", info.appId, info.versionId)

	local data = {
		name = info.entity.name,
		children = info.entity.children
	}
	local success, response = request.Post(uri, data)
	if not success then
		LogError("[LUIS_ENTITIES_COMPOSITE:CreateAppEntity] Error creating APP COMPOSITE ENTITIES on appId '%s' versionId: '%s'. Response: '%s'", info.appId, info.versionId, json.encode(response))
		return false, response
	end

	local entityId = table.concat(response)
	LogInfo("[LUIS_ENTITIES_COMPOSITE:CreateAppEntity] Success created APP COMPOSITE ENTITIES on appId '%s', entityId: '%s' versionId: '%s'.", info.appId, entityId, info.versionId)

	return true, entityId
end

function RenameAppEntity (info)
	assert(info)
	assert(info.appId)
	assert(info.entityId)
	assert(info.versionId)
	assert(info.entity)

	local uri = MakeCompleteURI("APPS", "%s/versions/%s/compositeentities/%s", info.appId, info.versionId, info.entityId)

	local data = {
		---- Requerido
		name = info.entity.name,
		children = info.entity.children
	}
	local success, response = request.Put(uri, data)
	if not success then
		LogError("[LUIS_ENTITIES_COMPOSITE:RenameAppEntity] Error renaming APP COMPOSITE ENTITIES '%s' on appId '%s' versionId: '%s'. Response: '%s'", info.entityId, info.appId, info.versionId, json.encode(response))
		return false, response
	end

	LogInfo("[LUIS_ENTITIES_COMPOSITE:RenameAppEntity] Success renamed APP COMPOSITE ENTITIES '%s' on appId '%s' versionId: '%s'.", info.entityId, info.appId, info.versionId)

	return true, response
end

function DeleteAppEntity (appId, entityId, versionId)
	assert(appId)
	assert(entityId)
	assert(versionId)

	local uri = MakeCompleteURI("APPS", "%s/versions/%s/compositeentities/%s", appId, versionId, entityId)

	local success, response = request.Delete(uri)
	if not success then
		LogError("[LUIS_ENTITIES_COMPOSITE:DeleteAppEntity] Error deleting APP COMPOSITE ENTITIES '%s' versionId: '%s' on appId '%s'. Response: '%s'", entityId, versionId, appId, json.encode(response))
		return false, response
	end

	LogInfo("[LUIS_ENTITIES_COMPOSITE:DeleteAppEntity] Success deleted APP COMPOSITE ENTITIES '%s' versionId: '%s' on appId '%s'.", entityId, versionId, appId)

	return true, response
end
