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"`
}

type PCAConfig struct {
	CAIdentifier string `json:"caIdentifier,omitempty"`
}

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
	VPCPeeringNameKey          = "cloud.pingcap.com/vpcPeeringName" // ref to vpc peering name
	KeyNameKey                 = "cloud.pingcap.com/keyName"        // ref to key name
	RegionKey                  = "cloud.pingcap.com/region"
	TenantIDKey                = "cloud.pingcap.com/tenantId"
	PrivateLinkServiceNameKey  = "cloud.pingcap.com/privateLinkServiceName"
	PrivateLinkEndpointNameKey = "cloud.pingcap.com/privateLinkEndpointName"
	DataPlaneIDKey             = "cloud.pingcap.com/dataplaneId"
	ManageKey                  = "cloud.pingcap.com/manage"

	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"

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

	// SubnetType is used to record subnet type, supported values: node, pod, plsNAT, apiserver
	SubnetTypeKey       = "cloud.pingcap.com/subnetType"
	NodeSubnetType      = "node"
	PodSubnetType       = "pod"
	PLSNATSubnetType    = "plsNAT"
	APIServerSubnetType = "apiserver"
)

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

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

const (
	ConditionReasonXPResourceReady      string = "CrossplaneResourceReady"
	ConditionReasonXPResourceNotReady   string = "CrossplaneResourceNotReady"
	ConditionReasonKubeOperationFailed  string = "KubeOperationFailed"
	ConditionReasonKubeOperationSuccess string = "KubeOperationSuccess"
	ConditionReasonAPICallFailed        string = "APICallFailed"
	ConditionReasonAPICallUnExpected    string = "APICallUnExpected"
	ConditionReasonAPICallSuccess       string = "APICallSuccess"
)

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
}
