package bun

import (
	
	
	
	

	
	
)

type m2mModel struct {
	*sliceTableModel
	baseTable *schema.Table
	rel       *schema.Relation

	baseValues map[internal.MapKey][]reflect.Value
	structKey  []interface{}
}

var _ tableModel = (*m2mModel)(nil)

func ( *relationJoin) *m2mModel {
	 := .BaseModel.Table()
	 := .JoinModel.(*sliceTableModel)
	 := baseValues(, .PKs)
	if len() == 0 {
		return nil
	}
	 := &m2mModel{
		sliceTableModel: ,
		baseTable:       ,
		rel:             .Relation,

		baseValues: ,
	}
	if !.sliceOfPtr {
		.strct = reflect.New(.table.Type).Elem()
	}
	return 
}

func ( *m2mModel) ( context.Context,  *sql.Rows) (int, error) {
	,  := .Columns()
	if  != nil {
		return 0, 
	}

	.columns = 
	 := makeDest(, len())

	var  int

	for .Next() {
		if .sliceOfPtr {
			.strct = reflect.New(.table.Type).Elem()
		} else {
			.strct.Set(.table.ZeroValue)
		}
		.structInited = false

		.scanIndex = 0
		.structKey = .structKey[:0]
		if  := .Scan(...);  != nil {
			return 0, 
		}

		if  := .parkStruct();  != nil {
			return 0, 
		}

		++
	}
	if  := .Err();  != nil {
		return 0, 
	}

	return , nil
}

func ( *m2mModel) ( interface{}) error {
	 := .columns[.scanIndex]
	.scanIndex++

	,  := .table.FieldMap[]
	if ! {
		return .scanM2MColumn(, )
	}

	if  := .ScanValue(.strct, );  != nil {
		return 
	}

	for ,  := range .rel.M2MBaseFields {
		if .Name == .Name {
			.structKey = append(.structKey, .Value(.strct).Interface())
			break
		}
	}

	return nil
}

func ( *m2mModel) ( string,  interface{}) error {
	for ,  := range .rel.M2MBaseFields {
		if .Name ==  {
			 := reflect.New(.IndirectType).Elem()
			if  := .Scan(, );  != nil {
				return 
			}
			.structKey = append(.structKey, .Interface())
			break
		}
	}

	,  := .scanColumn(, )
	return 
}

func ( *m2mModel) () error {
	,  := .baseValues[internal.NewMapKey(.structKey)]
	if ! {
		return fmt.Errorf(
			"bun: m2m relation=%s does not have base %s with key=%q (check join conditions)",
			.rel.Field.GoName, .baseTable, .structKey)
	}

	for ,  := range  {
		if .sliceOfPtr {
			.Set(reflect.Append(, .strct.Addr()))
		} else {
			.Set(reflect.Append(, .strct))
		}
	}

	return nil
}