package v1alpha1

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

type InternetPhase string

const (
	InternetPhasePending        InternetPhase = "Pending"
	InternetPhaseReadyForCreate InternetPhase = "ReadyForCreate"
	InternetPhaseCreating       InternetPhase = "Creating"
	InternetPhaseFailed         InternetPhase = "Failed"
	InternetPhaseActive         InternetPhase = "Active"
	InternetPhaseReadyForDelete InternetPhase = "ReadyForDelete"
	InternetPhaseDeleting       InternetPhase = "Deleting"
	InternetPhaseDeleted        InternetPhase = "Deleted"
)

const (
	// for aws
	AnnotationKeyOwnCrossplaneNameInternetGateway = "cloud.pingcap.com/own-crossplane-name-internetgateway"
	AnnotationKeyOwnCrossplaneNameS3Gateway       = "cloud.pingcap.com/own-crossplane-name-s3gateway"
	// internet use AnnotationKeyOwnCrossplaneNameVPC to derive address name on aws
	// for gcp
	// internet also use AnnotationKeyOwnCrossplaneNameNetwor to derive address name on gcp
	AnnotationKeyOwnCrossplaneNameRouter = "cloud.pingcap.com/own-crossplane-name-router"
	// if the internet is originated from gardener, set the annotation to true
	AnnotationKeyOriginatedFromGardener = "cloud.pingcap.com/originated-from-gardener"
)

func IsOriginatedFromGardener(obj metav1.Object) bool {
	return obj.GetAnnotations()[AnnotationKeyOriginatedFromGardener] == "true"
}

// +kubebuilder:object:root=true
// +kubebuilder:resource:categories=regionserver
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="PHASE",type="string",JSONPath=".status.phase"
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
// VPC is the Schema for the Internet API
type Internet struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   InternetSpec   `json:"spec,omitempty"`
	Status InternetStatus `json:"status,omitempty"`
}

type InternetSpec struct {
	Provider string     `json:"provider"`
	Region   string     `json:"region"`
	VPCRef   *Reference `json:"vpcRef"`
}

type InternetStatus struct {
	// +optional
	Phase InternetPhase `json:"phase"`
	// +optional
	Reason string `json:"reason"`
	// +optional
	InternetGateway InternetGateway `json:"internetGateway"`
	// +optional
	IPAddresses []IPAddress `json:"ipAddresses"`
	// +optional
	NATs []NAT `json:"nats"`
	// +optional
	RouteTables []RouteTable `json:"routeTables"`
	// +optional
	Routes []Route `json:"routes"`
	// +optional
	CloudRouters []CloudRouter `json:"cloudRouters"`
	// +optional
	VPCID string `json:"vpcId"`
	// +optional
	ExternalIPs []string `json:"externalIPs,omitempty"`
	// +optional
	S3GatewayEndpoint Endpoint `json:"s3GatewayEndpoint"`
	// SubnetAssociations is the subnet associations for the nat gateway, currently only used for azure
	// +optional
	SubnetAssociations []SubnetAssociation `json:"subnetAssociations,omitempty"`
	// IPAssociations is the ip associations for the nat gateway, currently only used for azure
	// +optional
	IPAssociations []IPAssociation `json:"ipAssociations,omitempty"`
}

type IPAssociation struct {
	// +optional
	Name string `json:"name,omitempty"`
	// +optional
	IPAssociationID string `json:"ipAssociationId,omitempty"`
}

type SubnetAssociation struct {
	// +optional
	Name string `json:"name,omitempty"`
	// +optional
	SubnetAssociationID string `json:"subnetAssociationId,omitempty"`
}

type Endpoint struct {
	// +optional
	Name string `json:"name"`
	// +optional
	EndpointID string `json:"endpointId"`
}

type InternetGateway struct {
	InternetGatewayID string `json:"internetGatewayId"`
	Name              string `json:"name"`
}

type RouteTable struct {
	Name         string `json:"name"`
	RouteTableID string `json:"routeTableId"`
}

type Route struct {
	Name          string `json:"name"`
	RouteTableRef string `json:"routeTableRef"`
}

// GloudRouter defines gcp cloud router info
type CloudRouter struct {
	Name          string      `json:"name"`
	CloudRouterID uint64      `json:"cloudRouterId"`
	NATs          []RouterNAT `json:"nats"`
}

type RouterNAT struct {
	Name string   `json:"name"`
	IPs  []string `json:"ips"`
}

type IPAddress struct {
	// +optional
	Name string `json:"name,omitempty"`
	// +optional
	AllocationID string `json:"allocationId,omitempty"`
	// IP is the public IP address, currently only used for azure
	// +optional
	IP string `json:"ip,omitempty"`
}

func FindIPAddressByName(ips []IPAddress, name string) *IPAddress {
	for _, ip := range ips {
		if ip.Name == name {
			return &ip
		}
	}
	return nil
}

type NAT struct {
	Name         string `json:"name"`
	NATGatewayID string `json:"natGatewayId"`
}

func FindNATByName(nats []NAT, name string) *NAT {
	for _, nat := range nats {
		if nat.Name == name {
			return &nat
		}
	}
	return nil
}

// +kubebuilder:object:root=true
type InternetList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []Internet `json:"items"`
}

func init() {
	SchemeBuilder.Register(&Internet{}, &InternetList{})
}
