package tools

import (
	"strings"

	"cloud.o-forge.io/core/oc-lib/config"
)

type DataType int

// DataType - Enum for the different types of resources in db accessible from the outside
const (
	INVALID DataType = iota
	DATA_RESOURCE
	PROCESSING_RESOURCE
	STORAGE_RESOURCE
	COMPUTE_RESOURCE
	WORKFLOW_RESOURCE
	WORKFLOW
	WORKFLOW_EXECUTION
	WORKSPACE
	PEER
	COLLABORATIVE_AREA
	RULE
	BOOKING
	WORKFLOW_HISTORY
	WORKSPACE_HISTORY
	ORDER
	PURCHASE_RESOURCE
	LIVE_DATACENTER
	LIVE_STORAGE
	BILL
	NATIVE_TOOL
	EXECUTION_VERIFICATION
	ALLOWED_IMAGE
	SERVICE_RESOURCE
	DYNAMIC_RESOURCE
	LIVE_SERVICE
	PAYMENT
	REFUND
	DISCOUNT
	SUBSCRIPTION
)

var NOAPI = func() string {
	return ""
}
var CATALOGAPI = func() string {
	return config.GetConfig().InternalCatalogAPI
}
var SHAREDAPI = func() string {
	return config.GetConfig().InternalSharedAPI
}
var WORKFLOWAPI = func() string {
	return config.GetConfig().InternalWorkflowAPI
}
var WORKSPACEAPI = func() string {
	return config.GetConfig().InternalWorkspaceAPI
}
var PEERSAPI = func() string {
	return config.GetConfig().InternalPeerAPI
}
var DATACENTERAPI = func() string {
	return config.GetConfig().InternalDatacenterAPI
}

var SCHEDULERAPI = func() string {
	return config.GetConfig().InternalSchedulerAPI
}

var PURCHASEAPI = func() string {
	return config.GetConfig().InternalCatalogAPI + "/purchase"
}

// Bind the standard API name to the data type
var InnerDefaultAPI = [...]func() string{
	NOAPI,
	CATALOGAPI,
	CATALOGAPI,
	CATALOGAPI,
	CATALOGAPI,
	CATALOGAPI,
	WORKFLOWAPI,
	NOAPI,
	WORKSPACEAPI,
	PEERSAPI,
	SHAREDAPI,
	SHAREDAPI,
	SCHEDULERAPI,
	NOAPI,
	NOAPI,
	NOAPI,
	PURCHASEAPI,
	DATACENTERAPI,
	DATACENTERAPI,
	NOAPI,
	CATALOGAPI,
	SCHEDULERAPI,
	DATACENTERAPI,
	CATALOGAPI,
	CATALOGAPI,
	DATACENTERAPI,
	NOAPI,
	NOAPI,
	NOAPI,
	NOAPI,
}

// Bind the standard data name to the data type
var Str = [...]string{
	"invalid",
	"data_resource",
	"processing_resource",
	"storage_resource",
	"compute_resource",
	"workflow_resource",
	"workflow",
	"workflow_execution",
	"workspace",
	"peer",
	"collaborative_area",
	"rule",
	"booking",
	"workflow_history",
	"workspace_history",
	"order",
	"purchase_resource",
	"live_datacenter",
	"live_storage",
	"bill",
	"native_tool",
	"execution_verification",
	"allowed_image",
	"service_resource",
	"dynamic_resource",
	"live_service",
	"payment",
	"refund",
	"discount",
	"subscription",
}

func FromString(comp string) int {
	for i, str := range Str {
		if str == comp {
			return i
		}
	}
	return -1
}

func FromInt(i int) string {
	return Str[i]
}

func (d DataType) InnerAPI() string { // API - Returns the API name of the data type
	return InnerDefaultAPI[d]()
}

func (d DataType) String() string { // String - Returns the string name of the data type
	if d < 0 {
		return ""
	}
	return Str[d]
}

// EnumIndex - Creating common behavior - give the type a EnumIndex functio
func (d DataType) EnumIndex() int {
	return int(d)
}

func DataTypeList() []DataType {
	return []DataType{DATA_RESOURCE, PROCESSING_RESOURCE, STORAGE_RESOURCE, COMPUTE_RESOURCE, WORKFLOW_RESOURCE,
		WORKFLOW, WORKFLOW_EXECUTION, WORKSPACE, PEER, COLLABORATIVE_AREA, RULE, BOOKING, WORKFLOW_HISTORY, WORKSPACE_HISTORY,
		ORDER, PURCHASE_RESOURCE,
		LIVE_DATACENTER, LIVE_STORAGE, BILL, NATIVE_TOOL, EXECUTION_VERIFICATION, ALLOWED_IMAGE, SERVICE_RESOURCE, DYNAMIC_RESOURCE, LIVE_SERVICE,
		PAYMENT, REFUND, DISCOUNT, SUBSCRIPTION}
}

type PropalgationMessage struct {
	DataType int          `json:"datatype"`
	Action   PubSubAction `json:"action"`
	Payload  []byte       `json:"payload"`
}

type PubSubAction int

const (
	PB_SEARCH PubSubAction = iota
	PB_SEARCH_RESPONSE
	PB_CREATE
	PB_UPDATE
	PB_DELETE
	PB_PLANNER
	PB_CLOSE_PLANNER
	PB_CONSIDERS
	PB_ADMIRALTY_CONFIG
	PB_MINIO_CONFIG
	PB_PVC_CONFIG
	PB_CLOSE_SEARCH
	NONE
	PB_OBSERVE
	PB_OBSERVE_CLOSE
	// PB_PROPAGATE is used by oc-discovery to broadcast a peer's online/offline
	// state to other oc-discovery nodes in the federation via PROPALGATION_EVENT.
	PB_PROPAGATE
	// PB_SOURCE_PRESIGN is sent by oc-datacenter to request a pre-signed Minio URL
	// for a private source resource (isReachable=false, Phase 4).
	// oc-discovery routes it to the resource owner peer via ProtocolSourcePresignResource.
	PB_SOURCE_PRESIGN
)

func GetActionString(ss string) PubSubAction {
	switch ss {
	case "search":
		return PB_SEARCH
	case "create":
		return PB_CREATE
	case "update":
		return PB_UPDATE
	case "delete":
		return PB_DELETE
	case "search_response":
		return PB_SEARCH_RESPONSE
	case "planner":
		return PB_PLANNER
	case "close_planner":
		return PB_CLOSE_PLANNER
	case "considers":
		return PB_CONSIDERS
	case "admiralty_config":
		return PB_ADMIRALTY_CONFIG
	case "minio_config":
		return PB_MINIO_CONFIG
	case "close_search":
		return PB_CLOSE_SEARCH
	case "observe":
		return PB_OBSERVE
	case "observe_close":
		return PB_OBSERVE_CLOSE
	case "propagate":
		return PB_PROPAGATE
	case "source_presign":
		return PB_SOURCE_PRESIGN
	default:
		return NONE
	}
}

// path aligns with PubSubAction iota values for String().
var path = []string{
	"search",           // 0  PB_SEARCH
	"search_response",  // 1  PB_SEARCH_RESPONSE
	"create",           // 2  PB_CREATE
	"update",           // 3  PB_UPDATE
	"delete",           // 4  PB_DELETE
	"planner",          // 5  PB_PLANNER
	"close_planner",    // 6  PB_CLOSE_PLANNER
	"considers",        // 7  PB_CONSIDERS
	"admiralty_config", // 8  PB_ADMIRALTY_CONFIG
	"minio_config",     // 9  PB_MINIO_CONFIG
	"pvc_config",       // 10 PB_PVC_CONFIG
	"close_search",     // 11 PB_CLOSE_SEARCH
	"none",             // 12 NONE
	"observe",          // 13 PB_OBSERVE
	"observe_close",    // 14 PB_OBSERVE_CLOSE
	"propagate",        // 15 PB_PROPAGATE
	"source_presign",   // 16 PB_SOURCE_PRESIGN
}

func (m PubSubAction) String() string {
	if int(m) >= len(path) {
		return "unknown"
	}
	return strings.ToUpper(path[m])
}
