package orm

import (
	
	
	
	

	
)

var errModelNil = errors.New("pg: Model(nil)")

type useQueryOne interface {
	useQueryOne() bool
}

type HooklessModel interface {
	// Init is responsible to initialize/reset model state.
	// It is called only once no matter how many rows were returned.
	Init() error

	// NextColumnScanner returns a ColumnScanner that is used to scan columns
	// from the current row. It is called once for every row.
	NextColumnScanner() ColumnScanner

	// AddColumnScanner adds the ColumnScanner to the model.
	AddColumnScanner(ColumnScanner) error
}

type Model interface {
	HooklessModel

	AfterScanHook
	AfterSelectHook

	BeforeInsertHook
	AfterInsertHook

	BeforeUpdateHook
	AfterUpdateHook

	BeforeDeleteHook
	AfterDeleteHook
}

func ( interface{}) (Model, error) {
	return newModel(, false)
}

func ( []interface{}) (Model, error) {
	if len() > 1 {
		return Scan(...), nil
	}
	return newModel([0], true)
}

func ( interface{},  bool) (Model, error) {
	switch value := .(type) {
	case Model:
		return , nil
	case HooklessModel:
		return newModelWithHookStubs(), nil
	case types.ValueScanner, sql.Scanner:
		if ! {
			return nil, fmt.Errorf("pg: Model(unsupported %T)", )
		}
		return Scan(), nil
	}

	 := reflect.ValueOf()
	if !.IsValid() {
		return nil, errModelNil
	}
	if .Kind() != reflect.Ptr {
		return nil, fmt.Errorf("pg: Model(non-pointer %T)", )
	}

	if .IsNil() {
		 := .Type().Elem()
		if .Kind() == reflect.Struct {
			return newStructTableModel(GetTable()), nil
		}
		return nil, errModelNil
	}

	 = .Elem()

	if .Kind() == reflect.Interface {
		if !.IsNil() {
			 = .Elem()
			if .Kind() != reflect.Ptr {
				return nil, fmt.Errorf("pg: Model(non-pointer %s)", .Type().String())
			}
		}
	}

	switch .Kind() {
	case reflect.Struct:
		if .Type() != timeType {
			return newStructTableModelValue(), nil
		}
	case reflect.Slice:
		 := sliceElemType()
		switch .Kind() {
		case reflect.Struct:
			if  != timeType {
				return newSliceTableModel(, ), nil
			}
		case reflect.Map:
			if  := validMap();  != nil {
				return nil, 
			}
			 := .Addr().Interface().(*[]map[string]interface{})
			return newMapSliceModel(), nil
		}
		return newSliceModel(, ), nil
	case reflect.Map:
		 := .Type()
		if  := validMap();  != nil {
			return nil, 
		}
		 := .Addr().Interface().(*map[string]interface{})
		return newMapModel(), nil
	}

	if ! {
		return nil, fmt.Errorf("pg: Model(unsupported %T)", )
	}
	return Scan(), nil
}

type modelWithHookStubs struct {
	hookStubs
	HooklessModel
}

func ( HooklessModel) Model {
	return modelWithHookStubs{
		HooklessModel: ,
	}
}

func ( reflect.Type) error {
	if .Key().Kind() != reflect.String || .Elem().Kind() != reflect.Interface {
		return fmt.Errorf("pg: Model(unsupported %s, expected *map[string]interface{})",
			.String())
	}
	return nil
}