package schema

import (
	
	
	
)

type tableInProgress struct {
	table *Table

	init1Once sync.Once
	init2Once sync.Once
}

func ( *Table) *tableInProgress {
	return &tableInProgress{
		table: ,
	}
}

func ( *tableInProgress) () bool {
	var  bool
	.init1Once.Do(func() {
		.table.init1()
		 = true
	})
	return 
}

func ( *tableInProgress) () bool {
	var  bool
	.init2Once.Do(func() {
		.table.init2()
		 = true
	})
	return 
}

type Tables struct {
	dialect Dialect
	tables  sync.Map

	mu         sync.RWMutex
	inProgress map[reflect.Type]*tableInProgress
}

func ( Dialect) *Tables {
	return &Tables{
		dialect:    ,
		inProgress: make(map[reflect.Type]*tableInProgress),
	}
}

func ( *Tables) ( ...interface{}) {
	for ,  := range  {
		_ = .Get(reflect.TypeOf().Elem())
	}
}

func ( *Tables) ( reflect.Type) *Table {
	return .table(, false)
}

func ( *Tables) ( reflect.Type) *Table {
	return .table(, true)
}

func ( *Tables) ( reflect.Type,  bool) *Table {
	 = indirectType()
	if .Kind() != reflect.Struct {
		panic(fmt.Errorf("got %s, wanted %s", .Kind(), reflect.Struct))
	}

	if ,  := .tables.Load();  {
		return .(*Table)
	}

	.mu.Lock()

	if ,  := .tables.Load();  {
		.mu.Unlock()
		return .(*Table)
	}

	var  *Table

	 := .inProgress[]
	if  == nil {
		 = newTable(.dialect, )
		 = newTableInProgress()
		.inProgress[] = 
	} else {
		 = .table
	}

	.mu.Unlock()

	.init1()
	if  {
		return 
	}

	if .init2() {
		.mu.Lock()
		delete(.inProgress, )
		.tables.Store(, )
		.mu.Unlock()
	}

	.dialect.OnTable()

	for ,  := range .FieldMap {
		if .UserSQLType == "" {
			.UserSQLType = .DiscoveredSQLType
		}
		if .CreateTableSQLType == "" {
			.CreateTableSQLType = .UserSQLType
		}
	}

	return 
}

func ( *Tables) ( string) *Table {
	var  *Table
	.tables.Range(func(,  interface{}) bool {
		 := .(*Table)
		if .TypeName ==  {
			 = 
			return false
		}
		return true
	})
	return 
}

func ( *Tables) ( string) *Table {
	var  *Table
	.tables.Range(func(,  interface{}) bool {
		 := .(*Table)
		if .Name ==  {
			 = 
			return false
		}
		return true
	})
	return 
}