{{GOLANG_HEADER}}

package {{GOLANG_PACKAGE}}

import (
	"database/sql"
	"time"

	"github.com/jinzhu/copier"
	"gorm.io/gorm"
)

type EmbeddedExample struct {
	Email string
}

type AnonymousEmbeddedExample struct {
	Anonymous bool
}

// Example https://gorm.io/docs/models.html
// https://gorm.io/docs/models.html#Fields-Tags
type Example struct {
	Id uint `gorm:"primary_key" json:"id" example:"1024"`

	// Index
	IndexField int `gorm:"index" example:"21"`
	// UniqueField      int `gorm:"unique"`// SQLite doesn't support
	UniqueIndexField int `gorm:"uniqueIndex" example:"12"`

	// Basic DataType
	ShortStringField     string  `gorm:"column:short_string_field;size:8" example:"短字符串字段"`
	LongStringField      string  `gorm:"column:long_string_field;size:256" example:"长字符串字段"` // specifies column data size/length
	LongTextField        string  `gorm:"column:long_text_field;type:text" example:"超长文本字段"`
	IntegerField         int     `gorm:"type:int" example:"3"`
	UnsignedIntegerField uint    `gorm:"type:uint" example:"4"`
	Float64Field         float64 `gorm:"type:float" example:"3.1415926535"`
	Float32Field         float32 `gorm:"type:float" example:"3.14159"`
	BinaryField          []byte  `gorm:"type:bytes" example:"255"`

	DefaultField string       `gorm:"default:value" example:"默认字段"`
	NotNullField sql.NullBool `gorm:"not null" json:"-" example:"禁止空值字段"`
	CheckField   string       `gorm:"check:integer_field > 5" example:"验证值字段"` // https://gorm.io/docs/constraints.html
	CommentField string       `gorm:"comment" example:"数据库注释字段"`               // add comment for field when migration

	// Embedded Struct
	// For anonymous fields, GORM will include its fields into its parent struct
	AnonymousEmbeddedExample

	// For a normal struct field, you can embed it with the tag embedded, for example:
	EmbeddedExample EmbeddedExample `gorm:"embedded"`

	// And you can use tag embeddedPrefix to add prefix to embedded fields’ db name, for example:
	EmbeddedExamplePrefix EmbeddedExample `gorm:"embedded;embeddedPrefix:embedded_"`

	// Field-Level Permission
	AllowReadAndCreate   string `gorm:"<-:create" example:"允许读和创建"`         // allow read and create
	AllowReadAndUpdate   string `gorm:"<-:update" example:"允许读和更新"`         // allow read and update
	AllowCreateAndUpdate string `gorm:"<-" example:"允许创建和更新"`               // allow read and write (create and update)
	ReadOnly             string `gorm:"->" example:"只读"`                    // readonly (disable write permission unless it configured )
	CreateOnly           string `gorm:"->:false;<-:create" example:"只允许创建"` // create only (disabled read from db)
	IgnoreWriteAndRead   string `gorm:"-" example:"忽略读写"`                   // ignore this field when write and read with struct
	IgnoreMigration      string `gorm:"migration" example:"忽略迁移"`           // // ignore this field when migration

	// Creating/Updating Time/Unix (Milli/Nano) Seconds Tracking
	CreatedAt             time.Time      `json:"created_at" example:"2020-07-14T16:20:00+08:00"` // Set to current time if it is zero on creating
	UpdatedAt             int            `json:"updated_at" example:"1678775400"`                // Set to current unix seconds on updating or if it is zero on creating
	UpdatedAtNanoSeconds  int64          `gorm:"autoUpdateTime:nano" example:"1678775400"`       // Use unix nano seconds as updating time
	UpdatedAtMilliSeconds int64          `gorm:"autoUpdateTime:milli" example:"1678775400"`      // Use unix milli seconds as updating time
	CreatedAtSeconds      int64          `gorm:"autoCreateTime" example:"1678775400"`            // Use unix seconds as creating time
	DeletedAt             gorm.DeletedAt `json:"-"`
}

func (Example) TableName() string {
	return "examples"
}

type Examples []Example

func (m *Example) CopyFrom(src interface{}) error {
	return copier.Copy(m, src)
}

func (m *Example) CopyTo(dst interface{}) error {
	return copier.Copy(dst, m)
}

// Create inserts a new row to the database.
func (m *Example) Create() error {
	return Db().Create(m).Error
}

// Save inserts a new row to the database or updates a row if the primary key already exists.
func (m *Example) Save() error {
	return Db().Save(m).Error
}

// Delete marks the entity as deleted.
func (m *Example) Delete() error {
	return Db().Delete(m).Error
}

func (m *Example) FindById(id uint) (err error) {
	err = Db().First(m, id).Error
	return
}

func (m *Example) FindByShortStringField(s string) (err error) {
	err = Db().First(m, "short_string_field = ?", s).Error
	return
}
