package fields

import (
	// "strings"

	"github.com/iancoleman/strcase"

	"gitlab.com/empowerlab/stack/lib-go/libdata"
)

// Many2manyFieldType contains the field type for Many2many
const Many2manyFieldType = libdata.FieldType("Many2manyType")

/*Many2many is the field type you can use in definition to declare a Many2many field.
 */
type Many2many struct {
	Name                string
	String              string
	Reference           string
	ReferenceDefinition *libdata.ModelDefinition
	TitleName           string
	DBName              string
}

// GetName return the name of the field.
func (f *Many2many) GetName() string {
	return f.Name
}

// Title return the title of the field.
func (f *Many2many) Title() string {
	titleName := strcase.ToCamel(f.Name)
	if f.TitleName != "" {
		titleName = f.TitleName
	}
	return titleName
}

// Title return the title of the field.
func (f *Many2many) NameWithoutUUID() string {
	return f.Name
}

// Title return the title of the field.
func (f *Many2many) TitleWithoutUUID() string {
	return f.Title()
}

// Snake return the name of the field, in snake_case. This is essentially used for database.
func (f *Many2many) Snake() string {
	dbName := strcase.ToSnake(f.Name)
	if f.DBName != "" {
		dbName = f.DBName
	}
	return dbName
}

// Type return the type of the field.
func (f *Many2many) Type() libdata.FieldType {
	return Many2manyFieldType
}

// Type return the type of the field.
func (f *Many2many) GoType() string {
	return libdata.STRING
}

// ProtoType return the protobuf type for this field.
func (f *Many2many) ProtoType() string {
	return f.GoType()
}

// ProtoType return the protobuf type for this field.
func (f *Many2many) DBType() *libdata.DBType {
	return nil
}

// Type return the type of the field.
func (f *Many2many) GraphqlType() string {
	return f.GetReference().Title()
}

// Type return the type of the field.
func (f *Many2many) GraphqlSchemaType() string {
	return f.GetReference().Title()
}

// GetReference return the name of referenced model, if this field is linked to another model.
func (f *Many2many) GetReferenceName() string {
	return f.Reference
}

// GetReferenceDefinition return the definition of referenced model,
// if this field is linked to another model.
func (f *Many2many) GetReference() *libdata.ModelDefinition {
	return f.ReferenceDefinition
}

// SetReferenceDefinition set the definition of referenced model,
// if this field is linked to another model.
func (f *Many2many) SetReference(d *libdata.ModelDefinition) {
	f.ReferenceDefinition = d
}

// GetInverseField return the inverse field, if applicable.
func (f *Many2many) GetInverseField() string {
	return ""
}

// GetRequired return if this field is required or not.
func (f *Many2many) GetRequired() bool {
	return false
}

// GetPrimaryKey return if this field is a primary key or not.
func (f *Many2many) GetPrimaryKey() bool {
	return false
}

func (f *Many2many) IsStored() bool {
	return false
}

func (f *Many2many) IsNested() bool {
	return true
}

//GetFieldData return the field information in a format exploimodel by templates.
// func (f *Many2many) GetFieldData() *libdata.FieldData {

// 	// var reference *ReferenceData
// 	// referenceDefinition := f.GetReferenceDefinition()
// 	// if referenceDefinition != nil {
// 	// 	reference = &ReferenceData{}
// 	// 	if referenceDefinition != f.Model {
// 	// 		reference = &ReferenceData{
// 	// 			Name:  referenceDefinition.GetTemplateData().Name,
// 	// 			Title: referenceDefinition.GetTemplateData().Title,
// 	// 		}
// 	// 	} else {
// 	// 		reference = &ReferenceData{
// 	// 			Name:  result.Name,
// 	// 			Title: result.Title,
// 	// 		}
// 	// 	}
// 	// }

// 	return &libdata.FieldData{
// 		Name:            f.Name,
// 		NameWithoutUUID: f.Name,
// 		// Type:             Many2manyFieldType.GoType(),
// 		// GoType:           Many2manyFieldType.GoType(),
// 		// ProtoType:        Many2manyFieldType.ProtoType(),
// 		Title:            f.Title(),
// 		TitleWithoutUUID: f.Title(),
// 		LesserTitle:      strings.Title(f.GetName()),
// 		Snake:            f.Snake(),
// 		Required:         false,
// 		Nested:           true,
// 		InverseField:     "",
// 		// Definition:       f,
// 	}
// }
