package resource

const (
	WorkloadNodeReady    WorkloadNodePhase = "Ready"
	WorkloadNodeNotReady WorkloadNodePhase = "NotReady"
)

// WorkloadNode is a workload node api object
// The WorkloadNode is used for running workloads like Sysbench or other testing workloads
type WorkloadNode struct {
	ResourceHandle `json:",inline"`
	Spec           WorkloadNodeSpec   `json:"spec"`
	Status         WorkloadNodeStatus `json:"status,omitempty"`
	Qos            *QosClaim          `json:"qos,omitempty"`
}

type WorkloadNodeSpec struct {
	LoadBalancer WorkloadNodeLoadBalancer `json:"loadBalancer"`
	Container    WorkloadUnit             `json:"container"`
	Replicas     int32                    `json:"replicas,omitempty" default:"1"`
	Artifact     WorkloadNodeArtifact     `json:"artifact"`
}

type WorkloadNodeLoadBalancer struct {
	ContainerPort int32  `json:"containerPort" default:"80"`
	ServiceType   string `json:"serviceType" default:"ClusterIP"`
}

// WorkloadUnit is a single workload unit that you want to run within a container or vm
type WorkloadUnit struct {
	Name  string `json:"name"`
	Image string `json:"image"`

	Resources         ResourceRequirements `json:"resources,omitempty"`
	CGroupMountMode   *string              `json:"cgroupMountMode,omitempty"`
	VolumeMount       VolumeMount          `json:"volumeMount,omitempty"`
	StorageClassName  *string              `json:"storageClassName,omitempty"`
	AdditionalVolumes []AdditionalVolume   `json:"additionalVolumes,omitempty"`

	Env        map[string]string `json:"env,omitempty"`
	Command    []string          `json:"command,omitempty"`
	Args       []string          `json:"args,omitempty"`
	WorkingDir string            `json:"workingDir,omitempty"`
	Port       int32             `json:"port"`

	// set to Always since we usually use the nightly image, e.g: hub.pingcap.net/qa/dumpling:release-5.0
	ImagePullPolicy ImagePullPolicy   `json:"imagePullPolicy" default:"Always"`
	NodeSelector    map[string]string `json:"nodeSelector,omitempty"`
	Labels          map[string]string `json:"labels,omitempty"`

	// SecurityContext holds security configuration that will be applied to a workload
	SecurityContext *SecurityContext `json:"securityContext,omitempty"`

	// LivenessProbe and ReadinessProbe are probes to determine the health and readiness of a container
	LivenessProbe  *Probe `json:"livenessProbe,omitempty"`
	ReadinessProbe *Probe `json:"readinessProbe,omitempty"`
}

type AdditionalVolume struct {
	VolumeMountPath string `json:"volumeMountPath,omitempty"`
	VolumeSource    struct {
		PersistentVolume *struct {
			PersistentVolumeName string `json:"persistentVolumeName,omitempty"`
			StorageClassName     string `json:"storageClassName,omitempty"`
			// ignores storageSize since it has no effect anyway
		} `json:"persistentVolume,omitempty"`
	} `json:"volumeSource,omitempty"`
}

type WorkloadNodeArtifact struct {
	ArtifactPaths []string `json:"artifactPaths"`
}

type WorkloadNodePhase string

type WorkloadNodeStatus struct {
	Phase WorkloadNodePhase `json:"phase"`
}

// ResourceName is the name identifying various resources in a ResourceList.
type ResourceName string

const (
	// CPU, in cores. (500m = .5 cores)
	CPU ResourceName = "cpu"
	// Memory, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)
	Memory ResourceName = "memory"
	// Volume size, in bytes (e,g. 5Gi = 5GiB = 5 * 1024 * 1024 * 1024)
	Storage ResourceName = "storage"
)

// Quantity is the fixed-point representation of a number, it's has the same format of k8s
//
// see: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-units-in-kubernetes
type Quantity string

type VolumeMount struct {
	MountPath string `json:"mountPath,omitempty"  default:"/data"` // mount to `/data` by default
}

type ExecAction struct {
	Command []string `json:"command,omitempty"`
}

type Probe struct {
	Exec                          *ExecAction `json:"exec,omitempty"`
	InitialDelaySeconds           int32       `json:"initialDelaySeconds,omitempty"`
	TimeoutSeconds                int32       `json:"timeoutSeconds,omitempty"`
	PeriodSeconds                 int32       `json:"periodSeconds,omitempty"`
	SuccessThreshold              int32       `json:"successThreshold,omitempty"`
	FailureThreshold              int32       `json:"failureThreshold,omitempty"`
	TerminationGracePeriodSeconds *int64      `json:"terminationGracePeriodSeconds,omitempty"`
}

// ResourceRequirements defines each resource's Quantity
type ResourceRequirements struct {
	// Requests describes the amount of compute resources required.
	Requests ResourceList `json:"requests,omitempty"`
	Limits   ResourceList `json:"limits,omitempty"`
}

// ResourceList alias map[ResourceName]Quantity
type ResourceList map[ResourceName]Quantity

// Capability represent POSIX capabilities type
type Capability string

// Capabilities Adds and removes POSIX capabilities from running containers.
type Capabilities struct {
	// Added capabilities
	Add []Capability `json:"add,omitempty"`
}

// SecurityContext holds security configuration that will be applied to a container.
type SecurityContext struct {
	// The capabilities to add/drop when running containers.
	Capabilities Capabilities `json:"capabilities"`
}
