






ll := import("@platforma-sdk/workflow-tengo:ll")

oop := import("@platforma-sdk/workflow-tengo:oop")
validation := import("@platforma-sdk/workflow-tengo:validation")
smart := import("@platforma-sdk/workflow-tengo:smart")
json := import("json")
constants := import("@platforma-sdk/workflow-tengo:exec.constants")
feats := import("@platforma-sdk/workflow-tengo:feats")

_RTYPE_QUOTA := { Name: "Quota", Version: "1" }







getResourceTypes := func(queueName) {

	result := feats.getResourceTypes(queueName)
	if !is_undefined(result) {
		return result
	}


	runnerType := constants.RUNNER_EXECUTOR
	if feats.hasBatch && queueName != constants.UI_TASKS_QUEUE {
		runnerType = constants.RUNNER_BATCH
	}
	return {
		runCommand:     { Name: "RunCommand/" + runnerType, Version: "2" },
		computeRequest: { Name: "ComputeRequest/" + runnerType, Version: "1" }
	}
}






quotaBuilder := func() {
	self := undefined

	queue_name := undefined
	cpu_request := undefined
	ram_request := undefined
	gpu_request := undefined

	self = ll.toStrict({







		queue: func(name) {
			validation.assertType(name, "string", "exec.quota.builder.queue: name of the queue should be a string")
			queue_name = name

			return self
		},







		cpu: func(amount) {
			validation.assertType(amount, ["or", "number", "null"], "exec.quota.builder.cpu: CPU amount should be a number")
			ll.assert(is_undefined(amount) || amount > 0, "exec.quota.builder.cpu: amount of cores should be greater than 0")
			cpu_request = amount

			return self
		},










		ram: func(amount) {
			validation.assertType(amount, ["or", "number", "string", "null"], "exec.quota.builder.ram: RAM amount should be a number or string")
			ll.assert(is_undefined(amount) || is_string(amount) || amount > 0, "exec.quota.builder.ram: amount in bytes should be greater than 0")
			ram_request = amount

			return self
		},








		gpuMemory: func(...args) {
			if len(args) == 0 {
				gpu_request = "1GiB"
			} else if len(args) == 1 {
				validation.assertType(args[0], "string", "exec.quota.builder.gpuMemory: argument must be a size string")
				gpu_request = args[0]
			} else {
				ll.panic("exec.quota.builder.gpuMemory: accepts 0 or 1 argument")
			}
			return self
		},






		build: func() {
			ll.assert(queue_name != "", "exec.quota.builder: queue name is mandatory and could not be empty string")

			data := {
				queue: queue_name
			}
			if !is_undefined(cpu_request) {
				data.cpuCores = cpu_request
			}
			if !is_undefined(ram_request) {
				data.memory = ram_request
			}
			if !is_undefined(gpu_request) {
				data.gpuMemory = gpu_request
			}

			return smart.ephemeralBuilder(_RTYPE_QUOTA, json.encode(data)).lockAndBuild()
		}
	})

	return self
}

_RTYPE_STORAGE_SPACE_REQUEST    := { Name: "StorageSpaceRequest", Version: "1" }
_SSR_FIELD_REQUEST                  := "request"    // input
_SSR_FIELD_ALLOCATION               := "allocation" // output

storageSpaceRequestBuilder := func() {
	self := undefined

	quota := undefined

	self = ll.toStrict({






		quota: func(ref) {
			validation.assertType(ref, validation.reference, "workdir.limits.quota: quota must be a valid reference to Quota resource")
			quota = ref

			return self
		},






		build: func() {
			ll.assert(smart.isReference(quota), "workdir.limits.build: quota of StorageSpaceRequest must be a valid reference")

			requestBuilder := smart.ephemeralBuilder(_RTYPE_STORAGE_SPACE_REQUEST)
			requestBuilder.getField(_SSR_FIELD_REQUEST).set(quota)

			requestRef := requestBuilder.lockAndBuild()

			return ll.toStrict(
				oop.inherit(requestRef, {
					allocation: requestRef.getField(_SSR_FIELD_ALLOCATION)
				})
			)
		}
	})

	return self
}


_CR_FIELD_REQUEST                   := "request"    // input
_CR_FIELD_ALLOCATION                := "allocation" // output

computeRequestBuilder := func() {
	self := undefined

	quota := undefined
	queue_name := undefined

	self = ll.toStrict({






		quota: func(ref) {
			validation.assertType(ref, validation.reference, "exec.limits.quota: quota must be a valid reference to Quota resource")
			quota = ref

			return self
		},






		queue: func(name) {
			validation.assertType(name, "string", "exec.limits.queue: queue name should be a string")
			queue_name = name

			return self
		},






		build: func() {
			ll.assert(smart.isReference(quota), "exec.limits.build: quota of ComputeRequest must be a valid reference")
			ll.assert(queue_name != "", "exec.limits.build: queue name is required for computeRequestBuilder")

			resourceTypes := getResourceTypes(queue_name)
			requestBuilder := smart.ephemeralBuilder(resourceTypes.computeRequest)

			requestBuilder.getField(_CR_FIELD_REQUEST).set(quota)

			requestRef := requestBuilder.lockAndBuild()

			return ll.toStrict(
				oop.inherit(requestRef, {
					allocation: requestRef.getField(_CR_FIELD_ALLOCATION)
				})
			)
		}
	})

	return self
}

export ll.toStrict({
	getResourceTypes:                getResourceTypes,
	quotaBuilder:                    quotaBuilder,
	storageSpaceRequestBuilder:      storageSpaceRequestBuilder,
	computeRequestBuilder:           computeRequestBuilder
})
