// Copyright Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Code generated by pilot/pkg/config/kube/crdclient/gen/types.go.tmpl DO NOT EDIT!

package crdclient

// This file contains Go definitions for Custom Resource Definition kinds
// to adhere to the idiomatic use of k8s API machinery.
// These definitions are synthesized from Istio configuration type descriptors
// as declared in the Istio config model.

import (
	"context"
	"fmt"
	metav1alpha1 "istio.io/api/meta/v1alpha1"

	versionedclient "istio.io/client-go/pkg/clientset/versioned"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
	gatewayapiclient "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned"

	"github.com/apache/dubbo-go-pixiu/pkg/config"
	"github.com/apache/dubbo-go-pixiu/pkg/config/schema/collections"

	extensionsv1alpha1 "istio.io/api/extensions/v1alpha1"
	networkingv1alpha3 "istio.io/api/networking/v1alpha3"
	networkingv1beta1 "istio.io/api/networking/v1beta1"
	securityv1beta1 "istio.io/api/security/v1beta1"
	telemetryv1alpha1 "istio.io/api/telemetry/v1alpha1"
	clientextensionsv1alpha1 "istio.io/client-go/pkg/apis/extensions/v1alpha1"
	clientnetworkingv1alpha3 "istio.io/client-go/pkg/apis/networking/v1alpha3"
	clientnetworkingv1beta1 "istio.io/client-go/pkg/apis/networking/v1beta1"
	clientsecurityv1beta1 "istio.io/client-go/pkg/apis/security/v1beta1"
	clienttelemetryv1alpha1 "istio.io/client-go/pkg/apis/telemetry/v1alpha1"

  extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
  corev1 "k8s.io/api/core/v1"
  appsv1 "k8s.io/api/apps/v1"
  admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
  apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
	gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
)

func create(ic versionedclient.Interface, sc gatewayapiclient.Interface, cfg config.Config, objMeta metav1.ObjectMeta) (metav1.Object, error) {
	switch cfg.GroupVersionKind {
{{- range . }}
  {{- if not .Readonly }}
	case collections.{{ .VariableName }}.Resource().GroupVersionKind():
		return {{.Client}}.{{ .ClientGroupPath }}().{{ .ClientTypePath }}({{if .Namespaced}}cfg.Namespace{{end}}).Create(context.TODO(), &{{ .ClientImport }}.{{ .Kind }}{
			ObjectMeta: objMeta,
			Spec:       *(cfg.Spec.(*{{ .APIImport }}.{{ .Kind }}{{ .TypeSuffix }})),
		}, metav1.CreateOptions{})
  {{- end }}
{{- end }}
	default:
		return nil, fmt.Errorf("unsupported type: %v", cfg.GroupVersionKind)
	}
}

func update(ic versionedclient.Interface, sc gatewayapiclient.Interface, cfg config.Config, objMeta metav1.ObjectMeta) (metav1.Object, error) {
	switch cfg.GroupVersionKind {
{{- range . }}
  {{- if not .Readonly }}
	case collections.{{ .VariableName }}.Resource().GroupVersionKind():
		return {{.Client}}.{{ .ClientGroupPath }}().{{ .ClientTypePath }}({{if .Namespaced}}cfg.Namespace{{end}}).Update(context.TODO(), &{{ .ClientImport }}.{{ .Kind }}{
			ObjectMeta: objMeta,
			Spec:       *(cfg.Spec.(*{{ .APIImport }}.{{ .Kind }}{{ .TypeSuffix }})),
		}, metav1.UpdateOptions{})
  {{- end }}
{{- end }}
	default:
		return nil, fmt.Errorf("unsupported type: %v", cfg.GroupVersionKind)
	}
}

func updateStatus(ic versionedclient.Interface, sc gatewayapiclient.Interface, cfg config.Config, objMeta metav1.ObjectMeta) (metav1.Object, error) {
    switch cfg.GroupVersionKind {
    {{- range . }}
      {{- if not .Readonly }}
      {{ if .StatusKind }}
    	case collections.{{ .VariableName }}.Resource().GroupVersionKind():
    		return {{.Client}}.{{ .ClientGroupPath }}().{{ .ClientTypePath }}({{if .Namespaced}}cfg.Namespace{{end}}).UpdateStatus(context.TODO(), &{{ .ClientImport }}.{{ .Kind }}{
    			ObjectMeta: objMeta,
    			Status:     *(cfg.Status.(*{{ .StatusAPIImport }}.{{ .StatusKind }})),
    		}, metav1.UpdateOptions{})
      {{- end }}
      {{- end }}
    {{- end }}
    	default:
    		return nil, fmt.Errorf("unsupported type: %v", cfg.GroupVersionKind)
    	}
}

func patch(ic versionedclient.Interface, sc gatewayapiclient.Interface, orig config.Config, origMeta metav1.ObjectMeta, mod config.Config, modMeta metav1.ObjectMeta, typ types.PatchType) (metav1.Object, error) {
	if orig.GroupVersionKind != mod.GroupVersionKind {
		return nil, fmt.Errorf("gvk mismatch: %v, modified: %v", orig.GroupVersionKind, mod.GroupVersionKind)
	}
    // TODO support setting field manager
	switch orig.GroupVersionKind {
{{- range . }}
  {{- if not .Readonly }}
    case collections.{{ .VariableName }}.Resource().GroupVersionKind():
        oldRes := &{{ .ClientImport }}.{{ .Kind }}{
            ObjectMeta: origMeta,
            Spec:       *(orig.Spec.(*{{ .APIImport }}.{{ .Kind }}{{ .TypeSuffix }})),
        }
        modRes := &{{ .ClientImport }}.{{ .Kind }}{
            ObjectMeta: modMeta,
            Spec:       *(mod.Spec.(*{{ .APIImport }}.{{ .Kind }}{{ .TypeSuffix }})),
        }
        patchBytes, err := genPatchBytes(oldRes, modRes, typ)
        if err != nil {
            return nil, err
        }
        return {{.Client}}.{{ .ClientGroupPath }}().{{ .ClientTypePath }}({{if .Namespaced}}orig.Namespace{{end}}).
            Patch(context.TODO(), orig.Name, typ, patchBytes, metav1.PatchOptions{FieldManager: "pilot-discovery"})
  {{- end }}
{{- end }}
	default:
		return nil, fmt.Errorf("unsupported type: %v", orig.GroupVersionKind)
	}
}


func delete(ic versionedclient.Interface, sc gatewayapiclient.Interface, typ config.GroupVersionKind, name, namespace string, resourceVersion *string) error {
	var deleteOptions metav1.DeleteOptions
	if resourceVersion != nil {
		deleteOptions.Preconditions = &metav1.Preconditions{ResourceVersion: resourceVersion}
	}
	switch typ {
{{- range . }}
  {{- if not .Readonly }}
	case collections.{{ .VariableName }}.Resource().GroupVersionKind():
		return {{.Client}}.{{ .ClientGroupPath }}().{{ .ClientTypePath }}({{if .Namespaced}}namespace{{end}}).Delete(context.TODO(), name, deleteOptions)
  {{- end }}
{{- end }}
	default:
		return fmt.Errorf("unsupported type: %v", typ)
	}
}

var translationMap = map[config.GroupVersionKind]func(r runtime.Object) config.Config{
{{- range . }}
	collections.{{ .VariableName }}.Resource().GroupVersionKind(): func(r runtime.Object) config.Config {
		obj := r.(*{{ .ClientImport }}.{{ .Kind }})
		return config.Config{
		  Meta: config.Meta{
		  	GroupVersionKind:  collections.{{ .VariableName }}.Resource().GroupVersionKind(),
		  	Name:              obj.Name,
		  	Namespace:         obj.Namespace,
		  	Labels:            obj.Labels,
		  	Annotations:       obj.Annotations,
		  	ResourceVersion:   obj.ResourceVersion,
		  	CreationTimestamp: obj.CreationTimestamp.Time,
		  	OwnerReferences:   obj.OwnerReferences,
		  	UID:               string(obj.UID),
		  	Generation:        obj.Generation,
		  },
		  Spec:   {{ if not .NoSpec }}&obj.Spec{{ else }}obj{{ end }},
      {{- if .StatusKind }}
		  Status: &obj.Status,
      {{- end }}
		}
	},
{{- end }}
}
