local json = require "cjson"
local request = require "luis.request"

module(..., package.seeall)

local m_instanceOwner
function SetOwner (instanceOwner)
	m_instanceOwner = instanceOwner
end

local m_defaultAppVersion = "3.0-PREVIEW" 

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

--[[
	Retorna los parametros:
		1) Si tiene paginado    : "?skip=0&take=2"
		2) Si no tiene paginado : ""
]]--
local function MakePagingParameters (params)
	local api = require "luis"
	return api.MakePagingParameters(params)
end

-- *******************************************************************************
-- API ENTITIES MACHINE LEARNED
-- -- *******************************************************************************

--[[
-----------------------------
MODELS - GET APPLICATION VERSION ENTITY INFOS
-----------------------------
	Gets information about the entity models.

	Request URL
	------------
		https://westus.api.cognitive.microsoft.com/luis/api/v2.0/apps/{appId}/versions/{versionId}/entities[?skip][&take]

	Request parameters
	------------
		appId string Format - guid. The application ID.

		versionId string The task version ID.

		skip (optional) integer The number of entries to skip. Default value is 0.

		take (optional) integer The number of entries to return. Maximum page size is 500. Default is 100.

	Request headers
	------------
		Ocp-Apim-Subscription-Key string Subscription key which provides access to this API. Found in your Cognitive Services accounts.

	Request body
	------------
		..

	Response 200
	------------
		[
		  {
			"id": "3d73462d-98f0-4dcd-8d30-fab9e65f2e73",
			"name": "DayOfWeek",
			"typeId": 1,
			"readableType": "Entity Extractor"
		  },
		  {
			"id": "b8e31be4-300f-455e-894b-6f079abca0a2",
			"name": "$Camera.AppName",
			"typeId": 1,
			"readableType": "Entity Extractor",
			"customPrebuiltDomainName": "Camera",
			"customPrebuiltModelName": "AppName"
		  }
		]

	Referencia: https://westus.dev.cognitive.microsoft.com/docs/services/5890b47c39e2bb17b84a55ff/operations/5890b47c39e2bb052c5b9c0f
]]--
function LoadAllAppEntities (appId, versionId, paginated)
	assert(appId)
	assert(versionId)

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

	local success, response = request.Get(uri)
	if not success then
		LogError("[LUIS_ENTITIES_MACHINE_LEARNED.v3.0_PREVIEW:LoadAllAppEntities] Error loading all APP MACHINE LEARNED ENTITIES on appId '%s' versionId: '%s'. Error: '%s'", appId, versionId, json.encode(response))
		return false, response
	end

	LogInfo("[LUIS_ENTITIES_MACHINE_LEARNED.v3.0_PREVIEW:LoadAllAppEntities] Success loaded all APP MACHINE LEARNED ENTITIES on appId '%s' versionId: '%s'.", appId, versionId)

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

--[[
-----------------------------
MODELS - GET ENTITY INFO
-----------------------------
	Gets information about the entity model.

	Request URL
	-----------------------------
		https://westus.api.cognitive.microsoft.com/luis/api/v2.0/apps/{appId}/versions/{versionId}/entities/{entityId}

	Request parameters
	-----------------------------
		appId string Format - guid. The application ID.

		versionId string The task version ID.

		entityId string Format - guid. The entity extractor ID.

	Request headers
	-----------------------------
		Ocp-Apim-Subscription-Key string Subscription key which provides access to this API. Found in your Cognitive Services accounts.
		Request body

	Response 200
	-----------------------------
		{
		  "id": "3d73462d-98f0-4dcd-8d30-fab9e65f2e73",
		  "name": "DayOfWeek",
		  "typeId": 1,
		  "readableType": "Entity Extractor"
		}


	Referencia: https://westus.dev.cognitive.microsoft.com/docs/services/5890b47c39e2bb17b84a55ff/operations/5890b47c39e2bb052c5b9c1d
]]--
function GetAppEntity (appId, entityId, versionId)
	assert(appId)
	assert(entityId)
	assert(versionId)

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

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

	LogInfo("[LUIS_ENTITIES_MACHINE_LEARNED.v3.0_PREVIEW:GetAppEntity] Success get APP MACHINE LEARNED ENTITIES '%s' on appId '%s' versionId: '%s'.", entityId, appId, versionId)

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

--[[
-----------------------------
MODELS - CREATE ENTITY
-----------------------------
	Adds an entity extractor to the application.

	Request URL
	------------
		https://{endpoint}/luis/authoring/v3.0-preview/apps/{appId}/versions/{versionId}/entities

	Request parameters
	------------
		appId string Format - guid. The application ID.
		versionId string The task version ID.

	Request headers
	------------
		Content-Type (optional) string Media type of the body sent to the API.
		Ocp-Apim-Subscription-Key string Subscription key which provides access to this API. Found in your Cognitive Services accounts.

	Request body
	------------
		A model object containing the name and children for the new entity extractor.
		The name of the entity must be unique in the application and must not be used by a prebuilt entity.

		application/json
		Sample
			{
				"name": "DayOfMonth",
				"children":[
					{
						"name": "day"
					},
					{
						"name": "month",
						"instanceOf": "datetimeV2"
					}
				]
			}

	Response 201
	------------
		The ID of the created model.

		"3d73462d-98f0-4dcd-8d30-fab9e65f2e73"

	Response 429
	------------
		Rate limit is exceeded.

	Response 400
	------------
		This error can be returned if the request's parameters are incorrect meaning the required parameters are missing, malformed, or too large.

		This error can be returned if the request's body is incorrect meaning the JSON is missing, malformed, or too large.

		This error can be returned if you are attempting to create an entity when the max entity count is exceeded.

		{
		"error": {
			"code": "BadArgument",
			"message": "An application cannot have more than 30 entities."
		}
		}

	Response 401
	------------
		You do not have access.

		Reasons can include:

		used endpoint subscription key, instead of authoring key
		invalid, malformed, or empty authoring key
		authoring key doesn't match region
		you are not the owner or collaborator
		invalid order of API calls

	Response 403
	------------
		Total monthly key quota limit exceeded

	Referencia: https://westus.dev.cognitive.microsoft.com/docs/services/luis-programmatic-apis-v3-0-preview/operations/5890b47c39e2bb052c5b9c0e
]]--
function CreateAppEntity (info)
	assert(type(info) == "table")
	assert(info.appId)
	assert(info.versionId)

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

	local data = {
		name = info.name,
		children = info.children
	}

	local success, response = request.Post(uri, data)
	if not success then
		LogError("[LUIS_ENTITIES_MACHINE_LEARNED.v3.0_PREVIEW:CreateAppEntity] Error creating APP MACHINE LEARNED 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_MACHINE_LEARNED.v3.0_PREVIEW:CreateAppEntity] Success created APP MACHINE LEARNED ENTITIES on appId '%s', entityId: '%s' versionId: '%s'.", info.appId, entityId, info.versionId)

	return true, entityId
end

--[[
-----------------------------
MODELS - UPDATE ENTITY EXTRACTOR
-----------------------------
	Updates the entity extractor.

	Request URL
	------------
		https://{endpoint}/luis/authoring/v3.0-preview/apps/{appId}/versions/{versionId}/entities/{entityId}

	Request parameters
	------------
		appId string Format - guid. The application ID.

		versionId string The task version ID.

		entityId string Format - guid. The entity extractor ID.

	Request headers
	------------
		Content-Type (optional) string Media type of the body sent to the API.
		Ocp-Apim-Subscription-Key string Subscription key which provides access to this API. Found in your Cognitive Services accounts.

	Request body
	------------
		An object containing the new entity extractor name and/or the "instanceOf" model.
		application/json
		Sample:
			{
				"name": "Reservation",
				"instanceOf": "geographyV2"
			}

	Response 200
	------------
		Empty response

	Referencia: https://westus.dev.cognitive.microsoft.com/docs/services/luis-programmatic-apis-v3-0-preview/operations/5d86d03a07924396d3217c27
]]--
function RenameAppEntity (info)
	assert(info)
	assert(info.appId)
	assert(info.entityId)
	assert(info.versionId)
	assert(info.name)

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

	local data = {
		-- Requerido
		name       = info.name,
		-- NO Requerido
		instanceOf = info.instanceOf
	}
	local success, response = request.Patch(uri, data)
	if not success then
		LogError("[LUIS_ENTITIES_MACHINE_LEARNED.v3.0_PREVIEW:RenameAppEntity] Error renaming APP 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_MACHINE_LEARNED.v3.0_PREVIEW:RenameAppEntity] Success renamed APP ENTITIES '%s' on appId '%s' versionId: '%s'.", info.entityId, info.appId, info.versionId)

	return true, response
end

--[[
-----------------------------
MODELS - DELETE ENTITY MODEL
-----------------------------
	Deletes an entity extractor from the application.

	Request URL
	------------
		https://westus.api.cognitive.microsoft.com/luis/api/v2.0/apps/{appId}/versions/{versionId}/entities/{entityId}

	Request parameters
	------------
		appId string Format - guid. The application ID.

		versionId string The task version ID.

		entityId string Format - guid. The entity extractor ID.

	Request headers
	------------
		Ocp-Apim-Subscription-Key string Subscription key which provides access to this API. Found in your Cognitive Services accounts.

	Request body
	------------

	Response 200
	------------
		Empty response

	Referencia: https://westus.dev.cognitive.microsoft.com/docs/services/5890b47c39e2bb17b84a55ff/operations/5890b47c39e2bb052c5b9c1f
]]--
function DeleteAppEntity (appId, entityId, versionId)
	assert(appId)
	assert(entityId)
	assert(versionId)

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

	local success, response = request.Delete(uri)
	if not success then
		LogError("[LUIS_ENTITIES_MACHINE_LEARNED.v3.0_PREVIEW:DeleteAppEntity] Error deleting APP MACHINE LEARNED ENTITY '%s' versionId: '%s' on appId '%s'. Response: '%s'", entityId, versionId, appId, json.encode(response))
		return false, response
	end

	LogInfo("[LUIS_ENTITIES_MACHINE_LEARNED.v3.0_PREVIEW:DeleteAppEntity] Success deleted APP MACHINE LEARNED ENTITY '%s' versionId: '%s' on appId '%s'.", entityId, versionId, appId)

	return true, response
end

--[[
-----------------------------
MODELS - CREATE ENTITY CHILD
-----------------------------
	Creates a single child in an existing entity model.

	Request URL
	------------
		https://{endpoint}/luis/authoring/v3.0-preview/apps/{appId}/versions/{versionId}/entities/{entityId}/children

	Request parameters
	------------
		appId string Format - guid. The application ID.
		versionId string The task version ID.
		entityIdstring The entity extractor ID

	Request headers
	------------
		Content-Type (optional) string Media type of the body sent to the API.
		Ocp-Apim-Subscription-Key string Subscription key which provides access to this API. Found in your Cognitive Services accounts.

	Request body
	------------
		A model object containing the name and the children of the new child model.

		application/json
		Sample
			{
				"name" : "dayOfWeek",
				"instanceOf": "datetimeV2",
				"children": [
					{
						"name": "dayNumber",
						"instanceOf": "number",
						"children": []
					}
				]
			}

	Response 201
	------------
		The ID of the created model.

		"3d73462d-98f0-4dcd-8d30-fab9e65f2e73"

	Response 429
	------------
		Rate limit is exceeded.

	Response 400
	------------
		This error can be returned if the request's parameters are incorrect meaning the required parameters are missing, malformed, or too large.

		This error can be returned if the request's body is incorrect meaning the JSON is missing, malformed, or too large.

		This error can be returned if you are attempting to create a composite entity child when the max child count is exceeded.

		"error": {
			"code": "BadArgument",
			"message": "Number of entity children cannot exceed 10"
		}

	Response 401
	------------
		You do not have access.

		Reasons can include:

		used endpoint subscription key, instead of authoring key
		invalid, malformed, or empty authoring key
		authoring key doesn't match region
		you are not the owner or collaborator
		invalid order of API calls

	Response 403
	------------
		Total monthly key quota limit exceeded

	Referencia: https://westus.dev.cognitive.microsoft.com/docs/services/luis-programmatic-apis-v3-0-preview/operations/5d86cf3c6a25a45529767d77
]]--
function CreateAppEntityChild (info)
	assert(type(info) == "table")
	assert(info.appId)
	assert(info.entityId)
	assert(info.versionId)

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

	local data = {
		name = info.name,
		instanceOf = info.instanceOf,
		children = info.children
	}

	local success, response = request.Post(uri, data)
	if not success then
		LogError("[LUIS_ENTITIES_MACHINE_LEARNED.v3.0_PREVIEW:CreateAppEntityChild] Error creating APP MACHINE LEARNED ENTITY CHILD. Parent Entity '%s' on appId '%s' versionId: '%s'. Response: '%s'", info.entityId, info.appId, info.versionId, json.encode(response))
		return false, response
	end

	local childEntityId = table.concat(response)
	LogInfo("[LUIS_ENTITIES_MACHINE_LEARNED.v3.0_PREVIEW:CreateAppEntityChild] Success created APP MACHINE LEARNED ENTITY CHILD '%s'. Parent Entity '%s' on appId '%s', entityId: '%s' versionId: '%s'.", childEntityId, info.entityId, info.appId, entityId, info.versionId)

	return true, childEntityId
end
