package v1alpha1

import (
	"encoding/json"

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

type APPRoutePhase string

const (
	APPRoutePhasePending  APPRoutePhase = "Pending"
	APPRoutePhaseCreating APPRoutePhase = "Creating"
	APPRoutePhaseFailed   APPRoutePhase = "Failed"
	APPRoutePhaseActive   APPRoutePhase = "Active"
	APPRoutePhaseDeleting APPRoutePhase = "Deleting"
)

// +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 APPRoute API
type APPRoute struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	Spec   APPRouteSpec   `json:"spec,omitempty"`
	Status APPRouteStatus `json:"status,omitempty"`
}

type APPRouteSpec struct {
	VPCRef    *Reference `json:"vpcRef"`
	APPBoxRef *Reference `json:"appboxRef"`
	// +optional
	// SharedBucketRef encodes the shared bucket controller specific spec
	SharedBucketRef *SharedBucketReference `json:"sharedBucketRef,omitempty"`
	// ForCluster encodes the cluster controller specific spec
	ForCluster string `json:"forCluster"`
}

type APPRouteStatus struct {
	Phase APPRoutePhase `json:"phase,omitempty"`
	// +optional
	Reason string `json:"reason,omitempty"`
}

type SharedBucketReference struct {
	ProviderConfigName string `json:"providerConfigName"`
	BucketName         string `json:"bucketName"`
	AccountID          string `json:"accountID"`
}

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

func init() {
	SchemeBuilder.Register(&APPRoute{}, &APPRouteList{})
}

// NOTE: do not use this method to set ForCluster, json encode proto.message is not deterministic.
func SetAPPRouteCluster(approute *APPRoute, cluster interface{}) error {
	data, err := json.Marshal(cluster)
	if err != nil {
		return err
	}

	approute.Spec.ForCluster = string(data)
	return nil
}
