local json = require "cjson"
local request = require "luis.request"
local luis_models = require("luis.models"):GetModels()
local utils = require "luis.utils"

module(..., package.seeall)

local m_instanceOwner
function SetOwner (instanceOwner)
	m_instanceOwner = instanceOwner
end

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

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

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

function LoadAllAppFeatures (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 GetLanguageStudioAccount (vcc) 

	LogInfo(" ------> GetLanguageStudioAccount - vcc: %s", vcc)

	local vccAzureLanguageStudioAccounts, totalVCCAzureLanguageStudioAccounts = LoadVCCAzureLanguageStudioAccount(vcc) 
	local azureLanguageStudio = {} 
	if totalVCCAzureLanguageStudioAccounts > 0 then 
		local firstKey = next(vccAzureLanguageStudioAccounts) 
  		azureLanguageStudio = vccAzureLanguageStudioAccounts[firstKey] 
	else
		azureLanguageStudio = {} 
	end 

    return azureLanguageStudio.resource_name, azureLanguageStudio.subscription_key_1
	
end

function LoadVCCAzureLanguageStudioAccount (vcc, vcc_id) 
	
	if type(vcc) == "table" then
		vcc = vcc_id
	end

	local vccAzureLanguageStudioAccounts = luis_models.VCCs.GetAzureLanguageStudioAccountsMsCognitiveServices(vcc)

	local total = utils.GetRowCount(vccAzureLanguageStudioAccounts)
	return vccAzureLanguageStudioAccounts, total
end

function LoadAllAppFeaturesPhraselist (appId, versionId, paginated)
	assert(appId)
	assert(versionId)

	local uri = MakeCompleteURI("APPS", "%s/versions/%s/phraselists", appId, versionId)
	uri = uri .. MakePagingParameters(paginated)

	local success, response = request.Get(uri)
	if not success then
		LogError("[LUIS_FEATURES:LoadAllAppFeaturesPhraselist] Error loading FEATURES PHRASELIST on appId '%s' versionId: '%s'. Error: '%s'", appId, versionId, json.encode(response))
		return false, response
	end

	LogInfo("[LUIS_FEATURES:LoadAllAppFeaturesPhraselist] Success loaded FEATURES PHRASELIST on appId '%s' versionId: '%s'.", appId, versionId)

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

function CreatePhraselist (info)
	assert(type(info) == "table")
	assert(info.appId)
	assert(info.versionId)
	assert(info.name)
	assert(info.phrases)

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

	local data = {
		name = info.name,
		phrases = info.phrases,
		isActive = info.isActive,
		isExchangeable = info.isExchangeable
	}
	local success, response = request.Post(uri, data)
	if not success then
		LogError("[LUIS_FEATURES:CreatePhraselist] Error creating FEATURES PHRASELIST on appId '%s' versionId: '%s'. Response: '%s'", info.appId, info.versionId, json.encode(response))
		return false, response
	end

	local phraseId = table.concat(response)
	LogInfo("[LUIS_FEATURES:CreatePhraselist] Success created FEATURES PHRASELIST on appId '%s', phraseId: '%s' versionId: '%s'.", info.appId, phraseId, info.versionId)

	return true, phraseId
end

function UpdatePhraselist (info)
	assert(info)
	assert(info.appId)
	assert(info.phraseListId)
	assert(info.versionId)
	assert(info.name)
	assert(info.phrases)

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

	local data = {
		name = info.name,
		phrases = info.phrases,
		isActive = info.isActive,
		isExchangeable = info.isExchangeable
	}
	local success, response = request.Put(uri, data)
	if not success then
		LogError("[LUIS_FEATURES:UpdatePhraselist] Error updating FEATURES PHRASELIST '%s' on appId '%s' versionId: '%s'. Response: '%s'", info.phraseListId, info.appId, info.versionId, json.encode(response))
		return false, response
	end

	LogInfo("[LUIS_FEATURES:UpdatePhraselist] Success updated FEATURES PHRASELIST '%s' on appId '%s' versionId: '%s'.", info.phraseListId, info.appId, info.versionId)

	return true, response
end

function DeletePhraselist (appId, phraseListId, versionId)
	assert(appId)
	assert(phraseListId)
	assert(versionId)

	local uri = MakeCompleteURI("APPS", "%s/versions/%s/phraselists/%s", appId, versionId, phraseListId)

	local success, response = request.Delete(uri)
	if not success then
		LogError("[LUIS_FEATURES:DeletePhraselist] Error deleting FEATURES PHRASELIST '%s' versionId: '%s' on appId '%s'. Response: '%s'", phraseListId, versionId, appId, json.encode(response))
		return false, response
	end

	LogInfo("[LUIS_FEATURES:DeletePhraselist] Success deleted FEATURES PHRASELIST '%s' versionId: '%s' on appId '%s'.", phraseListId, versionId, appId)

	return true, response
end