package v3

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

// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:resource:scope=Cluster

// DynamicSchema is the definition of a schema. Dynamic schemas are
// created and used internally by Rancher to generate CRDs and Norman
// API endpoints, and should not be created manually.
//
// Functionality for generating Rancher dynamic Norman API endpoints
// is limited. These endpoints are not backed by any Norman
// stores. Related fields will affect the definition of the Norman
// schema in Rancher but without stores these will have no useful
// effect. The schema definitions themselves will still be available
// in the Norman API.
// ---
// DynamicSchema is used by Rancher for generating dynamic
// provisioning and CAPI CRDs for Rancher node drivers: the machine
// pool configuration CRD, the InfrastructureMachineTemplate CRD, and
// the InfrastructureMachine CRD. Dynamic schemas are generated by
// Rancher from node and cluster drivers.
//
// It is also used by Rancher to generate meta-schemas that list node
// driver, kontainer driver, and credential config schemas as fields
// in the schema (see the "nodeconfig", "nodetemplateconfig",
// "cluster" and "credentialconfig" schemas). Some of these are used
// by the UI.
type DynamicSchema struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	// Specification of the desired behavior of the the dynamic schema. More info:
	// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
	Spec DynamicSchemaSpec `json:"spec"`
	// Most recent observed status of the dynamic schema. More info:
	// https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
	// +optional
	Status DynamicSchemaStatus `json:"status"`
}

type DynamicSchemaSpec struct {
	// SchemaName is the id under which the schema will be registered in the
	// Norman API collection of schemas. If unset, the dynamic schema
	// resource name will be used.
	// +optional
	SchemaName string `json:"schemaName,omitempty"`

	// Embed determines whether the ResourceFields of this schema should be
	// embedded into another Norman schema (EmbedType). When Embed is true,
	// updates after creation to this object don't affect its corresponding
	// Norman schema and will only change the fields of the EmbedType
	// schema.
	// +optional
	Embed bool `json:"embed,omitempty"`

	// EmbedType identifies the Norman schema into which the ResourceFields
	// of this object should be embedded in, when Embed is true.
	// +optional
	EmbedType string `json:"embedType,omitempty"`

	// PluralName is an alternate name used to reference collections of
	// resources of this schema in the Norman API.
	//
	// No Norman stores are defined for dynamic schemas, so no collections
	// can be retrieved through this name.
	// +optional
	PluralName string `json:"pluralName,omitempty"`

	// ResourceMethods is a list of http methods available for resources of
	// this Norman schema in the Norman API.
	//
	// No Norman stores are defined for dynamic schemas, so these methods
	// will always return an error.
	// +optional
	ResourceMethods []string `json:"resourceMethods,omitempty"`

	// ResourceFields defines the schema fields and their types.
	// +optional
	// ---
	// These are populated by Rancher to define which fields are supported
	// by a given node or kontainer driver. They are also used for
	// listing other schemas (see the "cluster", "nodeconfig",
	// "nodetemplateconfig" and "credentialconfig" generated schemas).
	ResourceFields map[string]Field `json:"resourceFields,omitempty"`

	// ResourceActions is the list of custom actions for this resource in
	// the Norman API.
	//
	// No API action handlers can be defined for dynamic schemas, so the
	// behavior of these actions cannot be defined.
	// +optional
	ResourceActions map[string]Action `json:"resourceActions,omitempty"`

	// CollectionMethods is a list of http methods available for collections
	// of resources of this schema in the Norman API.
	//
	// No Norman stores are defined for dynamic schemas, so these methods
	// will always return an error.
	// +optional
	CollectionMethods []string `json:"collectionMethods,omitempty"`

	// CollectionFields has no effect.
	// +optional
	CollectionFields map[string]Field `json:"collectionFields,omitempty"`

	// CollectionActions is the list of custom actions for collections of
	// resources of this schema in the Norman API.
	//
	// No action handlers can be defined for dynamic schemas, so the
	// behavior of these actions cannot be defined.
	// +optional
	CollectionActions map[string]Action `json:"collectionActions,omitempty"`

	// CollectionFilters are filters for listing collections of resources of
	// this schema. Each map key is a field that can be used as a filter.
	//
	// No Norman stores are defined for dynamic schemas, so no collections
	// can be retrieved to be filtered.
	// +optional
	CollectionFilters map[string]Filter `json:"collectionFilters,omitempty"`

	// IncludeableLinks has no effect.
	// +optional
	IncludeableLinks []string `json:"includeableLinks,omitempty"`

	// DynamicSchemaVersion is used to determine whether the Norman schema
	// should be updated when this object is updated. The schema is only
	// updated if the previous version differs. Rancher overwrites this
	// field.
	// +optional
	DynamicSchemaVersion string `json:"dynamicSchemaVersion,omitempty"`
}

type DynamicSchemaStatus struct {
	// Fake has no effect.
	// +optional
	Fake string `json:"fake,omitempty"`
}

type Field struct {
	// Type is the type of the field. Possible types are "string",
	// "password", "boolean", "int", "array[string]" or another schema name.
	// +optional
	Type string `json:"type,omitempty"`

	// Default is the default value for the field.
	// +optional
	Default Values `json:"default,omitempty"`

	// Unique has no effect.
	// +optional
	Unique bool `json:"unique,omitempty"`

	// Nullable indicates that a field in a CRD derived from this schema
	// will be nullable.
	//
	// It also indicates whether the field can take a null value in a valid
	// object of this schema in the Norman API.
	//
	// No Norman stores are defined for DynamicSchemas, so no resources of
	// this schema can be created in the Norman API.
	// +optional
	Nullable bool `json:"nullable,omitempty"`

	// Create indicates that this field should be excluded when creating a
	// new object of this schema through the Norman API. If a value is
	// provided for this field in a create request, it will be filtered out
	// and ignored.
	//
	// No Norman stores are defined for DynamicSchemas, so no resources of
	// this schema can be created in the Norman API.
	// +optional
	Create bool `json:"create,omitempty"`

	// Required indicates that a field in a CRD derived from this schema
	// will be required.
	//
	// It also indicates that this field is required when creating a new
	// object of this schema through the Norman API.
	//
	// No Norman stores are defined for DynamicSchemas, so no resources of
	// this schema can be created in the Norman API.
	// +optional
	Required bool `json:"required,omitempty"`

	// Update indicates that this field should remain unchanged when
	// updating an object of this schema through the Norman API. If a value
	// is provided for this field in an update request, it will be filtered
	// out and ignored.
	//
	// No Norman stores are defined for DynamicSchemas, so no resources of
	// this schema can be updated in the Norman API.
	// +optional
	Update bool `json:"update,omitempty"`

	// MinLength defines the "minLength" attribute for this field in a CRD
	// derived from this schema.
	//
	// It is also used to validate the length of the string representation
	// of this field in the Norman API.
	//
	// No Norman stores are defined for DynamicSchemas, so no resources of
	// this schema can be created in the Norman API.
	// +optional
	MinLength int64 `json:"minLength,omitempty"`

	// MaxLength defines the "maxLength" attribute for this field in a CRD
	// derived from this schema.
	//
	// It is also used to validate the length of the string representation
	// of this field in the Norman API.
	//
	// No Norman stores are defined for DynamicSchemas, so no resources of
	// this schema can be created in the Norman API.
	// +optional
	MaxLength int64 `json:"maxLength,omitempty"`

	// Min defines the "minimum" attribute for this field in a CRD derived
	// from this schema.
	//
	// It is also used to validate minimum value of this field in the Norman
	// API.
	//
	// No Norman stores are defined for DynamicSchemas, so no resources of
	// this schema can be created in the Norman API.
	// +optional
	Min int64 `json:"min,omitempty"`

	// Max defines the "maximum" attribute for this field in a CRD derived
	// from this schema.
	//
	// It is also used to validate maximum value of this field in the Norman
	// API.
	//
	// No Norman stores are defined for DynamicSchemas, so no resources of
	// this schema can be created in the Norman API.
	// +optional
	Max int64 `json:"max,omitempty"`

	// Options defines the "enum" attribute with valid values for this field
	// in a CRD derived from this schema.
	//
	// It is also used to validate the value of the string representation of
	// this field in the Norman API.
	//
	// No Norman stores are defined for DynamicSchemas, so no resources of
	// this schema can be created in the Norman API.
	// +optional
	Options []string `json:"options,omitempty"`

	// ValidChars defines a value for the "pattern" attribute with the
	// allowed characters for this field in a CRD derived from this schema.
	//
	// It is also used to validate the value of the string representation of
	// this field in the Norman API.
	//
	// No Norman stores are defined for DynamicSchemas, so no resources of
	// this schema can be created in the Norman API.
	// +optional
	ValidChars string `json:"validChars,omitempty"`

	// InvalidChars defines a value for the "pattern" attribute with the
	// disallowed characters for this field in a CRD derived from this
	// schema.
	//
	// It is also used to validate the value of the string representation of
	// this field in the Norman API.
	//
	// No Norman stores are defined for DynamicSchemas, so no resources of
	// this schema can be created in the Norman API.
	// +optional
	InvalidChars string `json:"invalidChars,omitempty"`

	// Description is the description of this field.
	// +optional
	// ---
	// This is used to generate descriptions for CRDs derived from the
	// schema.
	Description string `json:"description,omitempty"`

	// DynamicField indicates this field should be removed from a schema
	// when embedding another schema into it.
	// +optional
	DynamicField bool `json:"dynamicField,omitempty"`
}

// Values defines a default value for a Field. The value field will
// be selected according to the Type of the Field.
type Values struct {
	// StringValue is the default value for a Field of "string" or
	// "password" type.
	// +optional
	StringValue string `json:"stringValue"`
	// IntValue is the default value for a Field of "int" type.
	// +optional
	IntValue int `json:"intValue"`
	// BoolValue is the default value for a Field of "bool" type.
	// +optional
	BoolValue bool `json:"boolValue"`
	// StringSliceValue is the default value for a Field of "array[string]"
	// type.
	// +optional
	// +nullable
	StringSliceValue []string `json:"stringSliceValue"`
}

type Action struct {
	// Input is the input for a custom Norman API action.
	// +optional
	Input string `json:"input,omitempty"`

	// Output is the output for a custom Norman API action.
	// +optional
	Output string `json:"output,omitempty"`
}

type Filter struct {
	// Modifiers are the operators that can be used when filtering a
	// collection of resources in the Norman API.
	// +optional
	Modifiers []string `json:"modifiers,omitempty"`
}

type ListOpts struct {
	Filters map[string]string `json:"filters,omitempty"`
}
