package server

import (
	"k8s.io/apimachinery/pkg/api/meta"
	"k8s.io/apimachinery/pkg/runtime/schema"
)

// newMapper returns a fixed REST mapper for the supported resources.
// This code intentionally supports only a limited set of resources.
// GitLab Managed Resources is not GitOps.
// Use Flux if these objects are not enough to bootstrap your environment.
func newMapper() meta.RESTMapper {
	dm := meta.NewDefaultRESTMapper(nil)
	addBuiltInResources(dm)
	addFluxSourceControllerResources(dm)
	addFluxKustomizeControllerResources(dm)
	addFluxHelmControllerResources(dm)
	addFluxNotificationControllerResources(dm)
	return dm
}

func addBuiltInResources(dm *meta.DefaultRESTMapper) {
	coreGV1 := schema.GroupVersion{Group: "", Version: "v1"}
	rbacGV1 := schema.GroupVersion{Group: "rbac.authorization.k8s.io", Version: "v1"}
	dm.AddSpecific(
		coreGV1.WithKind("Namespace"),
		coreGV1.WithResource("namespaces"),
		coreGV1.WithResource("namespace"),
		meta.RESTScopeRoot,
	)
	dm.AddSpecific(
		coreGV1.WithKind("ServiceAccount"),
		coreGV1.WithResource("serviceaccounts"),
		coreGV1.WithResource("serviceaccount"),
		meta.RESTScopeNamespace,
	)
	dm.AddSpecific(
		rbacGV1.WithKind("RoleBinding"),
		rbacGV1.WithResource("rolebindings"),
		rbacGV1.WithResource("rolebinding"),
		meta.RESTScopeNamespace,
	)
}

// https://fluxcd.io/flux/components/source/
func addFluxSourceControllerResources(dm *meta.DefaultRESTMapper) {
	gv1 := schema.GroupVersion{Group: "source.toolkit.fluxcd.io", Version: "v1"}
	gv1beta2 := schema.GroupVersion{Group: "source.toolkit.fluxcd.io", Version: "v1beta2"}
	// https://fluxcd.io/flux/components/source/gitrepositories/
	// https://github.com/fluxcd/source-controller/blob/main/docs/spec/v1/gitrepositories.md
	dm.AddSpecific(
		gv1.WithKind("GitRepository"),
		gv1.WithResource("gitrepositories"),
		gv1.WithResource("gitrepository"),
		meta.RESTScopeNamespace,
	)
	// https://fluxcd.io/flux/components/source/helmrepositories/
	// https://github.com/fluxcd/source-controller/blob/main/docs/spec/v1/helmrepositories.md
	dm.AddSpecific(
		gv1.WithKind("HelmRepository"),
		gv1.WithResource("helmrepositories"),
		gv1.WithResource("helmrepository"),
		meta.RESTScopeNamespace,
	)
	// https://fluxcd.io/flux/components/source/helmcharts/
	// https://github.com/fluxcd/source-controller/blob/main/docs/spec/v1/helmcharts.md
	dm.AddSpecific(
		gv1.WithKind("HelmChart"),
		gv1.WithResource("helmcharts"),
		gv1.WithResource("helmchart"),
		meta.RESTScopeNamespace,
	)
	// https://fluxcd.io/flux/components/source/buckets/
	// https://github.com/fluxcd/source-controller/blob/main/docs/spec/v1/buckets.md
	dm.AddSpecific(
		gv1.WithKind("Bucket"),
		gv1.WithResource("buckets"),
		gv1.WithResource("bucket"),
		meta.RESTScopeNamespace,
	)
	// https://fluxcd.io/flux/components/source/ocirepositories/
	// https://github.com/fluxcd/source-controller/blob/main/docs/spec/v1beta2/ocirepositories.md
	dm.AddSpecific(
		gv1beta2.WithKind("OCIRepository"),
		gv1beta2.WithResource("ocirepositories"),
		gv1beta2.WithResource("ocirepository"),
		meta.RESTScopeNamespace,
	)
}

// https://fluxcd.io/flux/components/kustomize/
func addFluxKustomizeControllerResources(dm *meta.DefaultRESTMapper) {
	gv1 := schema.GroupVersion{Group: "kustomize.toolkit.fluxcd.io", Version: "v1"}
	// https://github.com/fluxcd/kustomize-controller/blob/main/docs/spec/v1/kustomizations.md
	dm.AddSpecific(
		gv1.WithKind("Kustomization"),
		gv1.WithResource("kustomizations"),
		gv1.WithResource("kustomization"),
		meta.RESTScopeNamespace,
	)
}

// https://fluxcd.io/flux/components/helm/
func addFluxHelmControllerResources(dm *meta.DefaultRESTMapper) {
	gv2 := schema.GroupVersion{Group: "helm.toolkit.fluxcd.io", Version: "v2"}
	// https://github.com/fluxcd/helm-controller/blob/main/docs/spec/v2/helmreleases.md
	dm.AddSpecific(
		gv2.WithKind("HelmRelease"),
		gv2.WithResource("helmreleases"),
		gv2.WithResource("helmrelease"),
		meta.RESTScopeNamespace,
	)
}

// https://fluxcd.io/flux/components/notification/
func addFluxNotificationControllerResources(dm *meta.DefaultRESTMapper) {
	gv1 := schema.GroupVersion{Group: "notification.toolkit.fluxcd.io", Version: "v1"}
	gv1beta3 := schema.GroupVersion{Group: "notification.toolkit.fluxcd.io", Version: "v1beta3"}
	// https://github.com/fluxcd/notification-controller/blob/main/docs/spec/v1beta3/alerts.md
	dm.AddSpecific(
		gv1beta3.WithKind("Alert"),
		gv1beta3.WithResource("alerts"),
		gv1beta3.WithResource("alert"),
		meta.RESTScopeNamespace,
	)
	// https://github.com/fluxcd/notification-controller/blob/main/docs/spec/v1beta3/providers.md
	dm.AddSpecific(
		gv1beta3.WithKind("Provider"),
		gv1beta3.WithResource("providers"),
		gv1beta3.WithResource("provider"),
		meta.RESTScopeNamespace,
	)
	// https://github.com/fluxcd/notification-controller/blob/main/docs/spec/v1/receivers.md
	dm.AddSpecific(
		gv1.WithKind("Receiver"),
		gv1.WithResource("receivers"),
		gv1.WithResource("receiver"),
		meta.RESTScopeNamespace,
	)
}
