// 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"

    	admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
    	appsv1 "k8s.io/api/apps/v1"
    	corev1 "k8s.io/api/core/v1"
    	extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
    	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
    	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    	"k8s.io/apimachinery/pkg/runtime"
    	"k8s.io/apimachinery/pkg/types"
    	gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
    	gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
    	gatewayapiclient "sigs.k8s.io/gateway-api/pkg/client/clientset/versioned"

    	extensionsv1alpha1 "istio.io/api/extensions/v1alpha1"
    	metav1alpha1 "istio.io/api/meta/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"
    	versionedclient "istio.io/client-go/pkg/clientset/versioned"
    	"istio.io/istio/pkg/config"
    	"istio.io/istio/pkg/config/schema/collections"
)

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 }}.{{ .ClientType }})),
		}, 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 }}.{{ .ClientType }})),
		}, 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 }}.{{ .ClientType }})),
        }
        modRes := &{{ .ClientImport }}.{{ .Kind }}{
            ObjectMeta: modMeta,
            Spec:       *(mod.Spec.(*{{ .APIImport }}.{{ .ClientType }})),
        }
        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 }}
}
