package table

import (
	"reflect"
	"sync"
)

var SchemeStore = newSchemeStore()

type RowExtractor func(obj any) []any

type scheme struct {
	Header       []string
	RowExtractor RowExtractor
}

type schemeStore struct {
	mu      sync.RWMutex
	schemes map[reflect.Type]*scheme
}

func newSchemeStore() *schemeStore {
	return &schemeStore{schemes: make(map[reflect.Type]*scheme)}
}

func (s *schemeStore) Add(obj any, header []string, extact RowExtractor) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.schemes[concreteTypeOf(obj)] = &scheme{
		Header:       header,
		RowExtractor: extact,
	}
}

func (s *schemeStore) Get(obj any) (*scheme, bool) {
	s.mu.RLock()
	defer s.mu.RUnlock()
	scheme, ok := s.schemes[concreteTypeOf(obj)]
	return scheme, ok
}

func concreteTypeOf(obj any) reflect.Type {
	objType := reflect.TypeOf(obj)
	for objType.Kind() == reflect.Ptr {
		objType = objType.Elem()
	}
	return objType
}
