// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.
// Code generated by gorm.io/gen. DO NOT EDIT.

package dao

import (
	"context"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"gorm.io/gorm/schema"

	"gorm.io/gen"
	"gorm.io/gen/field"

	"gorm.io/plugin/dbresolver"

	"github.com/bitmagnet-io/bitmagnet/internal/model"
)

func newTorrent(db *gorm.DB, opts ...gen.DOOption) torrent {
	_torrent := torrent{}

	_torrent.torrentDo.UseDB(db, opts...)
	_torrent.torrentDo.UseModel(&model.Torrent{})

	tableName := _torrent.torrentDo.TableName()
	_torrent.ALL = field.NewAsterisk(tableName)
	_torrent.InfoHash = field.NewField(tableName, "info_hash")
	_torrent.Name = field.NewString(tableName, "name")
	_torrent.Size = field.NewUint(tableName, "size")
	_torrent.Private = field.NewBool(tableName, "private")
	_torrent.CreatedAt = field.NewTime(tableName, "created_at")
	_torrent.UpdatedAt = field.NewTime(tableName, "updated_at")
	_torrent.FilesStatus = field.NewField(tableName, "files_status")
	_torrent.Extension = field.NewString(tableName, "extension")
	_torrent.FilesCount = field.NewField(tableName, "files_count")
	_torrent.Hint = torrentHasOneHint{
		db: db.Session(&gorm.Session{}),

		RelationField: field.NewRelation("Hint", "model.TorrentHint"),
	}

	_torrent.Contents = torrentHasManyContents{
		db: db.Session(&gorm.Session{}),

		RelationField: field.NewRelation("Contents", "model.TorrentContent"),
	}

	_torrent.Sources = torrentHasManySources{
		db: db.Session(&gorm.Session{}),

		RelationField: field.NewRelation("Sources", "model.TorrentsTorrentSource"),
		TorrentSource: struct {
			field.RelationField
		}{
			RelationField: field.NewRelation("Sources.TorrentSource", "model.TorrentSource"),
		},
	}

	_torrent.Files = torrentHasManyFiles{
		db: db.Session(&gorm.Session{}),

		RelationField: field.NewRelation("Files", "model.TorrentFile"),
	}

	_torrent.Pieces = torrentHasOnePieces{
		db: db.Session(&gorm.Session{}),

		RelationField: field.NewRelation("Pieces", "model.TorrentPieces"),
	}

	_torrent.Tags = torrentHasManyTags{
		db: db.Session(&gorm.Session{}),

		RelationField: field.NewRelation("Tags", "model.TorrentTag"),
	}

	_torrent.fillFieldMap()

	return _torrent
}

type torrent struct {
	torrentDo

	ALL         field.Asterisk
	InfoHash    field.Field
	Name        field.String
	Size        field.Uint
	Private     field.Bool
	CreatedAt   field.Time
	UpdatedAt   field.Time
	FilesStatus field.Field
	Extension   field.String
	FilesCount  field.Field
	Hint        torrentHasOneHint

	Contents torrentHasManyContents

	Sources torrentHasManySources

	Files torrentHasManyFiles

	Pieces torrentHasOnePieces

	Tags torrentHasManyTags

	fieldMap map[string]field.Expr
}

func (t torrent) Table(newTableName string) *torrent {
	t.torrentDo.UseTable(newTableName)
	return t.updateTableName(newTableName)
}

func (t torrent) As(alias string) *torrent {
	t.torrentDo.DO = *(t.torrentDo.As(alias).(*gen.DO))
	return t.updateTableName(alias)
}

func (t *torrent) updateTableName(table string) *torrent {
	t.ALL = field.NewAsterisk(table)
	t.InfoHash = field.NewField(table, "info_hash")
	t.Name = field.NewString(table, "name")
	t.Size = field.NewUint(table, "size")
	t.Private = field.NewBool(table, "private")
	t.CreatedAt = field.NewTime(table, "created_at")
	t.UpdatedAt = field.NewTime(table, "updated_at")
	t.FilesStatus = field.NewField(table, "files_status")
	t.Extension = field.NewString(table, "extension")
	t.FilesCount = field.NewField(table, "files_count")

	t.fillFieldMap()

	return t
}

func (t *torrent) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
	_f, ok := t.fieldMap[fieldName]
	if !ok || _f == nil {
		return nil, false
	}
	_oe, ok := _f.(field.OrderExpr)
	return _oe, ok
}

func (t *torrent) fillFieldMap() {
	t.fieldMap = make(map[string]field.Expr, 15)
	t.fieldMap["info_hash"] = t.InfoHash
	t.fieldMap["name"] = t.Name
	t.fieldMap["size"] = t.Size
	t.fieldMap["private"] = t.Private
	t.fieldMap["created_at"] = t.CreatedAt
	t.fieldMap["updated_at"] = t.UpdatedAt
	t.fieldMap["files_status"] = t.FilesStatus
	t.fieldMap["extension"] = t.Extension
	t.fieldMap["files_count"] = t.FilesCount

}

func (t torrent) clone(db *gorm.DB) torrent {
	t.torrentDo.ReplaceConnPool(db.Statement.ConnPool)
	return t
}

func (t torrent) replaceDB(db *gorm.DB) torrent {
	t.torrentDo.ReplaceDB(db)
	return t
}

type torrentHasOneHint struct {
	db *gorm.DB

	field.RelationField
}

func (a torrentHasOneHint) Where(conds ...field.Expr) *torrentHasOneHint {
	if len(conds) == 0 {
		return &a
	}

	exprs := make([]clause.Expression, 0, len(conds))
	for _, cond := range conds {
		exprs = append(exprs, cond.BeCond().(clause.Expression))
	}
	a.db = a.db.Clauses(clause.Where{Exprs: exprs})
	return &a
}

func (a torrentHasOneHint) WithContext(ctx context.Context) *torrentHasOneHint {
	a.db = a.db.WithContext(ctx)
	return &a
}

func (a torrentHasOneHint) Session(session *gorm.Session) *torrentHasOneHint {
	a.db = a.db.Session(session)
	return &a
}

func (a torrentHasOneHint) Model(m *model.Torrent) *torrentHasOneHintTx {
	return &torrentHasOneHintTx{a.db.Model(m).Association(a.Name())}
}

type torrentHasOneHintTx struct{ tx *gorm.Association }

func (a torrentHasOneHintTx) Find() (result *model.TorrentHint, err error) {
	return result, a.tx.Find(&result)
}

func (a torrentHasOneHintTx) Append(values ...*model.TorrentHint) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Append(targetValues...)
}

func (a torrentHasOneHintTx) Replace(values ...*model.TorrentHint) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Replace(targetValues...)
}

func (a torrentHasOneHintTx) Delete(values ...*model.TorrentHint) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Delete(targetValues...)
}

func (a torrentHasOneHintTx) Clear() error {
	return a.tx.Clear()
}

func (a torrentHasOneHintTx) Count() int64 {
	return a.tx.Count()
}

type torrentHasManyContents struct {
	db *gorm.DB

	field.RelationField
}

func (a torrentHasManyContents) Where(conds ...field.Expr) *torrentHasManyContents {
	if len(conds) == 0 {
		return &a
	}

	exprs := make([]clause.Expression, 0, len(conds))
	for _, cond := range conds {
		exprs = append(exprs, cond.BeCond().(clause.Expression))
	}
	a.db = a.db.Clauses(clause.Where{Exprs: exprs})
	return &a
}

func (a torrentHasManyContents) WithContext(ctx context.Context) *torrentHasManyContents {
	a.db = a.db.WithContext(ctx)
	return &a
}

func (a torrentHasManyContents) Session(session *gorm.Session) *torrentHasManyContents {
	a.db = a.db.Session(session)
	return &a
}

func (a torrentHasManyContents) Model(m *model.Torrent) *torrentHasManyContentsTx {
	return &torrentHasManyContentsTx{a.db.Model(m).Association(a.Name())}
}

type torrentHasManyContentsTx struct{ tx *gorm.Association }

func (a torrentHasManyContentsTx) Find() (result []*model.TorrentContent, err error) {
	return result, a.tx.Find(&result)
}

func (a torrentHasManyContentsTx) Append(values ...*model.TorrentContent) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Append(targetValues...)
}

func (a torrentHasManyContentsTx) Replace(values ...*model.TorrentContent) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Replace(targetValues...)
}

func (a torrentHasManyContentsTx) Delete(values ...*model.TorrentContent) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Delete(targetValues...)
}

func (a torrentHasManyContentsTx) Clear() error {
	return a.tx.Clear()
}

func (a torrentHasManyContentsTx) Count() int64 {
	return a.tx.Count()
}

type torrentHasManySources struct {
	db *gorm.DB

	field.RelationField

	TorrentSource struct {
		field.RelationField
	}
}

func (a torrentHasManySources) Where(conds ...field.Expr) *torrentHasManySources {
	if len(conds) == 0 {
		return &a
	}

	exprs := make([]clause.Expression, 0, len(conds))
	for _, cond := range conds {
		exprs = append(exprs, cond.BeCond().(clause.Expression))
	}
	a.db = a.db.Clauses(clause.Where{Exprs: exprs})
	return &a
}

func (a torrentHasManySources) WithContext(ctx context.Context) *torrentHasManySources {
	a.db = a.db.WithContext(ctx)
	return &a
}

func (a torrentHasManySources) Session(session *gorm.Session) *torrentHasManySources {
	a.db = a.db.Session(session)
	return &a
}

func (a torrentHasManySources) Model(m *model.Torrent) *torrentHasManySourcesTx {
	return &torrentHasManySourcesTx{a.db.Model(m).Association(a.Name())}
}

type torrentHasManySourcesTx struct{ tx *gorm.Association }

func (a torrentHasManySourcesTx) Find() (result []*model.TorrentsTorrentSource, err error) {
	return result, a.tx.Find(&result)
}

func (a torrentHasManySourcesTx) Append(values ...*model.TorrentsTorrentSource) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Append(targetValues...)
}

func (a torrentHasManySourcesTx) Replace(values ...*model.TorrentsTorrentSource) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Replace(targetValues...)
}

func (a torrentHasManySourcesTx) Delete(values ...*model.TorrentsTorrentSource) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Delete(targetValues...)
}

func (a torrentHasManySourcesTx) Clear() error {
	return a.tx.Clear()
}

func (a torrentHasManySourcesTx) Count() int64 {
	return a.tx.Count()
}

type torrentHasManyFiles struct {
	db *gorm.DB

	field.RelationField
}

func (a torrentHasManyFiles) Where(conds ...field.Expr) *torrentHasManyFiles {
	if len(conds) == 0 {
		return &a
	}

	exprs := make([]clause.Expression, 0, len(conds))
	for _, cond := range conds {
		exprs = append(exprs, cond.BeCond().(clause.Expression))
	}
	a.db = a.db.Clauses(clause.Where{Exprs: exprs})
	return &a
}

func (a torrentHasManyFiles) WithContext(ctx context.Context) *torrentHasManyFiles {
	a.db = a.db.WithContext(ctx)
	return &a
}

func (a torrentHasManyFiles) Session(session *gorm.Session) *torrentHasManyFiles {
	a.db = a.db.Session(session)
	return &a
}

func (a torrentHasManyFiles) Model(m *model.Torrent) *torrentHasManyFilesTx {
	return &torrentHasManyFilesTx{a.db.Model(m).Association(a.Name())}
}

type torrentHasManyFilesTx struct{ tx *gorm.Association }

func (a torrentHasManyFilesTx) Find() (result []*model.TorrentFile, err error) {
	return result, a.tx.Find(&result)
}

func (a torrentHasManyFilesTx) Append(values ...*model.TorrentFile) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Append(targetValues...)
}

func (a torrentHasManyFilesTx) Replace(values ...*model.TorrentFile) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Replace(targetValues...)
}

func (a torrentHasManyFilesTx) Delete(values ...*model.TorrentFile) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Delete(targetValues...)
}

func (a torrentHasManyFilesTx) Clear() error {
	return a.tx.Clear()
}

func (a torrentHasManyFilesTx) Count() int64 {
	return a.tx.Count()
}

type torrentHasOnePieces struct {
	db *gorm.DB

	field.RelationField
}

func (a torrentHasOnePieces) Where(conds ...field.Expr) *torrentHasOnePieces {
	if len(conds) == 0 {
		return &a
	}

	exprs := make([]clause.Expression, 0, len(conds))
	for _, cond := range conds {
		exprs = append(exprs, cond.BeCond().(clause.Expression))
	}
	a.db = a.db.Clauses(clause.Where{Exprs: exprs})
	return &a
}

func (a torrentHasOnePieces) WithContext(ctx context.Context) *torrentHasOnePieces {
	a.db = a.db.WithContext(ctx)
	return &a
}

func (a torrentHasOnePieces) Session(session *gorm.Session) *torrentHasOnePieces {
	a.db = a.db.Session(session)
	return &a
}

func (a torrentHasOnePieces) Model(m *model.Torrent) *torrentHasOnePiecesTx {
	return &torrentHasOnePiecesTx{a.db.Model(m).Association(a.Name())}
}

type torrentHasOnePiecesTx struct{ tx *gorm.Association }

func (a torrentHasOnePiecesTx) Find() (result *model.TorrentPieces, err error) {
	return result, a.tx.Find(&result)
}

func (a torrentHasOnePiecesTx) Append(values ...*model.TorrentPieces) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Append(targetValues...)
}

func (a torrentHasOnePiecesTx) Replace(values ...*model.TorrentPieces) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Replace(targetValues...)
}

func (a torrentHasOnePiecesTx) Delete(values ...*model.TorrentPieces) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Delete(targetValues...)
}

func (a torrentHasOnePiecesTx) Clear() error {
	return a.tx.Clear()
}

func (a torrentHasOnePiecesTx) Count() int64 {
	return a.tx.Count()
}

type torrentHasManyTags struct {
	db *gorm.DB

	field.RelationField
}

func (a torrentHasManyTags) Where(conds ...field.Expr) *torrentHasManyTags {
	if len(conds) == 0 {
		return &a
	}

	exprs := make([]clause.Expression, 0, len(conds))
	for _, cond := range conds {
		exprs = append(exprs, cond.BeCond().(clause.Expression))
	}
	a.db = a.db.Clauses(clause.Where{Exprs: exprs})
	return &a
}

func (a torrentHasManyTags) WithContext(ctx context.Context) *torrentHasManyTags {
	a.db = a.db.WithContext(ctx)
	return &a
}

func (a torrentHasManyTags) Session(session *gorm.Session) *torrentHasManyTags {
	a.db = a.db.Session(session)
	return &a
}

func (a torrentHasManyTags) Model(m *model.Torrent) *torrentHasManyTagsTx {
	return &torrentHasManyTagsTx{a.db.Model(m).Association(a.Name())}
}

type torrentHasManyTagsTx struct{ tx *gorm.Association }

func (a torrentHasManyTagsTx) Find() (result []*model.TorrentTag, err error) {
	return result, a.tx.Find(&result)
}

func (a torrentHasManyTagsTx) Append(values ...*model.TorrentTag) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Append(targetValues...)
}

func (a torrentHasManyTagsTx) Replace(values ...*model.TorrentTag) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Replace(targetValues...)
}

func (a torrentHasManyTagsTx) Delete(values ...*model.TorrentTag) (err error) {
	targetValues := make([]interface{}, len(values))
	for i, v := range values {
		targetValues[i] = v
	}
	return a.tx.Delete(targetValues...)
}

func (a torrentHasManyTagsTx) Clear() error {
	return a.tx.Clear()
}

func (a torrentHasManyTagsTx) Count() int64 {
	return a.tx.Count()
}

type torrentDo struct{ gen.DO }

type ITorrentDo interface {
	gen.SubQuery
	Debug() ITorrentDo
	WithContext(ctx context.Context) ITorrentDo
	WithResult(fc func(tx gen.Dao)) gen.ResultInfo
	ReplaceDB(db *gorm.DB)
	ReadDB() ITorrentDo
	WriteDB() ITorrentDo
	As(alias string) gen.Dao
	Session(config *gorm.Session) ITorrentDo
	Columns(cols ...field.Expr) gen.Columns
	Clauses(conds ...clause.Expression) ITorrentDo
	Not(conds ...gen.Condition) ITorrentDo
	Or(conds ...gen.Condition) ITorrentDo
	Select(conds ...field.Expr) ITorrentDo
	Where(conds ...gen.Condition) ITorrentDo
	Order(conds ...field.Expr) ITorrentDo
	Distinct(cols ...field.Expr) ITorrentDo
	Omit(cols ...field.Expr) ITorrentDo
	Join(table schema.Tabler, on ...field.Expr) ITorrentDo
	LeftJoin(table schema.Tabler, on ...field.Expr) ITorrentDo
	RightJoin(table schema.Tabler, on ...field.Expr) ITorrentDo
	Group(cols ...field.Expr) ITorrentDo
	Having(conds ...gen.Condition) ITorrentDo
	Limit(limit int) ITorrentDo
	Offset(offset int) ITorrentDo
	Count() (count int64, err error)
	Scopes(funcs ...func(gen.Dao) gen.Dao) ITorrentDo
	Unscoped() ITorrentDo
	Create(values ...*model.Torrent) error
	CreateInBatches(values []*model.Torrent, batchSize int) error
	Save(values ...*model.Torrent) error
	First() (*model.Torrent, error)
	Take() (*model.Torrent, error)
	Last() (*model.Torrent, error)
	Find() ([]*model.Torrent, error)
	FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Torrent, err error)
	FindInBatches(result *[]*model.Torrent, batchSize int, fc func(tx gen.Dao, batch int) error) error
	Pluck(column field.Expr, dest interface{}) error
	Delete(...*model.Torrent) (info gen.ResultInfo, err error)
	Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
	UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
	Updates(value interface{}) (info gen.ResultInfo, err error)
	UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error)
	UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error)
	UpdateColumns(value interface{}) (info gen.ResultInfo, err error)
	UpdateFrom(q gen.SubQuery) gen.Dao
	Attrs(attrs ...field.AssignExpr) ITorrentDo
	Assign(attrs ...field.AssignExpr) ITorrentDo
	Joins(fields ...field.RelationField) ITorrentDo
	Preload(fields ...field.RelationField) ITorrentDo
	FirstOrInit() (*model.Torrent, error)
	FirstOrCreate() (*model.Torrent, error)
	FindByPage(offset int, limit int) (result []*model.Torrent, count int64, err error)
	ScanByPage(result interface{}, offset int, limit int) (count int64, err error)
	Scan(result interface{}) (err error)
	Returning(value interface{}, columns ...string) ITorrentDo
	UnderlyingDB() *gorm.DB
	schema.Tabler
}

func (t torrentDo) Debug() ITorrentDo {
	return t.withDO(t.DO.Debug())
}

func (t torrentDo) WithContext(ctx context.Context) ITorrentDo {
	return t.withDO(t.DO.WithContext(ctx))
}

func (t torrentDo) ReadDB() ITorrentDo {
	return t.Clauses(dbresolver.Read)
}

func (t torrentDo) WriteDB() ITorrentDo {
	return t.Clauses(dbresolver.Write)
}

func (t torrentDo) Session(config *gorm.Session) ITorrentDo {
	return t.withDO(t.DO.Session(config))
}

func (t torrentDo) Clauses(conds ...clause.Expression) ITorrentDo {
	return t.withDO(t.DO.Clauses(conds...))
}

func (t torrentDo) Returning(value interface{}, columns ...string) ITorrentDo {
	return t.withDO(t.DO.Returning(value, columns...))
}

func (t torrentDo) Not(conds ...gen.Condition) ITorrentDo {
	return t.withDO(t.DO.Not(conds...))
}

func (t torrentDo) Or(conds ...gen.Condition) ITorrentDo {
	return t.withDO(t.DO.Or(conds...))
}

func (t torrentDo) Select(conds ...field.Expr) ITorrentDo {
	return t.withDO(t.DO.Select(conds...))
}

func (t torrentDo) Where(conds ...gen.Condition) ITorrentDo {
	return t.withDO(t.DO.Where(conds...))
}

func (t torrentDo) Order(conds ...field.Expr) ITorrentDo {
	return t.withDO(t.DO.Order(conds...))
}

func (t torrentDo) Distinct(cols ...field.Expr) ITorrentDo {
	return t.withDO(t.DO.Distinct(cols...))
}

func (t torrentDo) Omit(cols ...field.Expr) ITorrentDo {
	return t.withDO(t.DO.Omit(cols...))
}

func (t torrentDo) Join(table schema.Tabler, on ...field.Expr) ITorrentDo {
	return t.withDO(t.DO.Join(table, on...))
}

func (t torrentDo) LeftJoin(table schema.Tabler, on ...field.Expr) ITorrentDo {
	return t.withDO(t.DO.LeftJoin(table, on...))
}

func (t torrentDo) RightJoin(table schema.Tabler, on ...field.Expr) ITorrentDo {
	return t.withDO(t.DO.RightJoin(table, on...))
}

func (t torrentDo) Group(cols ...field.Expr) ITorrentDo {
	return t.withDO(t.DO.Group(cols...))
}

func (t torrentDo) Having(conds ...gen.Condition) ITorrentDo {
	return t.withDO(t.DO.Having(conds...))
}

func (t torrentDo) Limit(limit int) ITorrentDo {
	return t.withDO(t.DO.Limit(limit))
}

func (t torrentDo) Offset(offset int) ITorrentDo {
	return t.withDO(t.DO.Offset(offset))
}

func (t torrentDo) Scopes(funcs ...func(gen.Dao) gen.Dao) ITorrentDo {
	return t.withDO(t.DO.Scopes(funcs...))
}

func (t torrentDo) Unscoped() ITorrentDo {
	return t.withDO(t.DO.Unscoped())
}

func (t torrentDo) Create(values ...*model.Torrent) error {
	if len(values) == 0 {
		return nil
	}
	return t.DO.Create(values)
}

func (t torrentDo) CreateInBatches(values []*model.Torrent, batchSize int) error {
	return t.DO.CreateInBatches(values, batchSize)
}

// Save : !!! underlying implementation is different with GORM
// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
func (t torrentDo) Save(values ...*model.Torrent) error {
	if len(values) == 0 {
		return nil
	}
	return t.DO.Save(values)
}

func (t torrentDo) First() (*model.Torrent, error) {
	if result, err := t.DO.First(); err != nil {
		return nil, err
	} else {
		return result.(*model.Torrent), nil
	}
}

func (t torrentDo) Take() (*model.Torrent, error) {
	if result, err := t.DO.Take(); err != nil {
		return nil, err
	} else {
		return result.(*model.Torrent), nil
	}
}

func (t torrentDo) Last() (*model.Torrent, error) {
	if result, err := t.DO.Last(); err != nil {
		return nil, err
	} else {
		return result.(*model.Torrent), nil
	}
}

func (t torrentDo) Find() ([]*model.Torrent, error) {
	result, err := t.DO.Find()
	return result.([]*model.Torrent), err
}

func (t torrentDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.Torrent, err error) {
	buf := make([]*model.Torrent, 0, batchSize)
	err = t.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
		defer func() { results = append(results, buf...) }()
		return fc(tx, batch)
	})
	return results, err
}

func (t torrentDo) FindInBatches(result *[]*model.Torrent, batchSize int, fc func(tx gen.Dao, batch int) error) error {
	return t.DO.FindInBatches(result, batchSize, fc)
}

func (t torrentDo) Attrs(attrs ...field.AssignExpr) ITorrentDo {
	return t.withDO(t.DO.Attrs(attrs...))
}

func (t torrentDo) Assign(attrs ...field.AssignExpr) ITorrentDo {
	return t.withDO(t.DO.Assign(attrs...))
}

func (t torrentDo) Joins(fields ...field.RelationField) ITorrentDo {
	for _, _f := range fields {
		t = *t.withDO(t.DO.Joins(_f))
	}
	return &t
}

func (t torrentDo) Preload(fields ...field.RelationField) ITorrentDo {
	for _, _f := range fields {
		t = *t.withDO(t.DO.Preload(_f))
	}
	return &t
}

func (t torrentDo) FirstOrInit() (*model.Torrent, error) {
	if result, err := t.DO.FirstOrInit(); err != nil {
		return nil, err
	} else {
		return result.(*model.Torrent), nil
	}
}

func (t torrentDo) FirstOrCreate() (*model.Torrent, error) {
	if result, err := t.DO.FirstOrCreate(); err != nil {
		return nil, err
	} else {
		return result.(*model.Torrent), nil
	}
}

func (t torrentDo) FindByPage(offset int, limit int) (result []*model.Torrent, count int64, err error) {
	result, err = t.Offset(offset).Limit(limit).Find()
	if err != nil {
		return
	}

	if size := len(result); 0 < limit && 0 < size && size < limit {
		count = int64(size + offset)
		return
	}

	count, err = t.Offset(-1).Limit(-1).Count()
	return
}

func (t torrentDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
	count, err = t.Count()
	if err != nil {
		return
	}

	err = t.Offset(offset).Limit(limit).Scan(result)
	return
}

func (t torrentDo) Scan(result interface{}) (err error) {
	return t.DO.Scan(result)
}

func (t torrentDo) Delete(models ...*model.Torrent) (result gen.ResultInfo, err error) {
	return t.DO.Delete(models)
}

func (t *torrentDo) withDO(do gen.Dao) *torrentDo {
	t.DO = *do.(*gen.DO)
	return t
}
