package v1alpha1

import (
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
	Finalizer = "dedicated.regionalserver.tidbcloud.com/finalizer"
	// annotation keys
	AnnotationKeyReconciliationPaused = "dedicated.regionalserver.tidbcloud.com/paused"
	// AnnotationKeyIsHiberated is used to control internet create task for hiberated network.
	AnnotationKeyIsHiberated = "cloud.pingcap.com/hiberated" // "true" or "false"

	// AnnotationKeyIdleStartTime is used to record the time when the resource is idle.
	// This annotation only used for the resource that need to be garbage collected and only set by the GC worker.
	AnnotationKeyIdelStartTime = "cloud.pingcap.com/idelStartTime"
	// AnnotationKeyReadyForDeleteStartTime is used to record the time when the resource is ready for delete.
	// This annotation only used for the resource that need to be garbage collected and only set by the GC worker.
	AnnotationKeyReadyForDeleteStartTime = "cloud.pingcap.com/readyForDeleteStartTime"
)

type Reference struct {
	Name      string `json:"name"`
	Namespace string `json:"namespace"`
}

const (
	VPCIDKey                  = "cloud.pingcap.com/vpcId"        // provider's vpc id
	AccountIDKey              = "cloud.pingcap.com/accountId"    // provider's account id
	VPCNameKey                = "cloud.pingcap.com/vpcName"      // ref to vpc name
	APPBoxNameKey             = "cloud.pingcap.com/appboxName"   // ref to appbox name
	InternetNameKey           = "cloud.pingcap.com/internetName" // ref to internet name
	PrivateLinkServiceNameKey = "cloud.pingcap.com/privateLinkServiceName"
	RegionKey                 = "cloud.pingcap.com/region"
	TenantIDKey               = "cloud.pingcap.com/tenantId"
	ProjectIDKey              = "cloud.pingcap.com/projectId"
	ClusterIDKey              = "cloud.pingcap.com/clusterId"
	ManageKey                 = "cloud.pingcap.com/manage"
	LoadBalancerIDKey         = "cloud.pingcap.com/loadBalancerId"
	IsLegacyKey               = "cloud.pingcap.com/legacy"
	SourceClusterIDKey        = "cloud.pingcap.com/sourceClusterId"
	SourceTidbGroupIDKey      = "cloud.pingcap.com/sourceTidbGroupId"
	TargetClusterIDKey        = "cloud.pingcap.com/targetClusterId"
	TargetTidbGroupIDKey      = "cloud.pingcap.com/targetTidbGroupId"

	TenantIDKeyPrefix  = "cloud.pingcap.com/tenant-"
	ProjectIDKeyPrefix = "cloud.pingcap.com/project-"
	ClusterIDKeyPrefix = "cloud.pingcap.com/cluster-"
	// Tag keys for tenant, project, cluster,
	// these tags will be propagated to the underlay resource and required by billing/report
	TagTenantKey      = "tags.tidbcloud.com/tenant"
	TagProjectKey     = "tags.tidbcloud.com/project"
	TagClusterKey     = "tags.tidbcloud.com/cluster"
	TagEnvironmentKey = "tags.tidbcloud.com/environment"

	SkipGCAnnotationKey = "cloud.pingcap.com/skipGC"
	SkipGCAnnotationVal = "true"

	// SubnetType is used to record subnet type, supported valued: node, pod, plsNAT, apiserver
	SubnetTypeKey = "cloud.pingcap.com/subnetType"

	NodeSubnetType              = "node"
	PodSubnetType               = "pod"
	PLSNATSubnetType            = "plsNAT"
	APIServerSubnetType         = "apiserver"
	SecondaryCidrNodeSubnetType = "secondaryCidrNode"
)

const (
	ManageFull     = "full"
	ManageReadOnly = "readonly"
	ManagePartial  = "partial"
)

const (
	// SecondaryCidrNamePrefix is the prefix of the secondary CIDR name
	SecondaryCidrNamePrefix = "cloud.pingcap.com/secondary-cidr-"

	SecondaryCidrStatusPending = "pending"
	SecondaryCidrStatusReady   = "ready"
	SecondaryCidrStatusFailed  = "failed"
)

const (
	TaskFirstPassTimeAnnotationKeyPrefix = "first-pass-when-creating.cloud.pingcap.com/"
)

type Conditions []metav1.Condition

func (c *Conditions) SetCondition(condition metav1.Condition) {
	if condition.Type == "" {
		return
	}
	currentCond, idx := c.GetCondition(condition.Type)
	if currentCond != nil && currentCond.Status == condition.Status && currentCond.Reason == condition.Reason && currentCond.Message == condition.Message {
		return
	}
	if idx != nil {
		(*c)[*idx] = condition
	} else {
		*c = append(*c, condition)
	}
}

func (c *Conditions) GetConditionEqualsTo(conditionType string, expected metav1.ConditionStatus) bool {
	condition, _ := c.GetCondition(conditionType)
	if condition == nil {
		return false
	}
	return condition.Status == expected
}

func (c *Conditions) GetCondition(conditionType string) (*metav1.Condition, *int) {
	for idx, cond := range *c {
		if cond.Type == conditionType {
			return &cond, &idx
		}
	}
	return nil, nil
}
