// Copyright 2022 schukai GmbH
// SPDX-License-Identifier: AGPL-3.0

package configuration

import (
	"github.com/fsnotify/fsnotify"
	"reflect"
	"strconv"
	"sync"
)

type fileWatch struct {
	sync.Mutex
	watcher     *fsnotify.Watcher
	watchList   map[string]string
	cancelWatch chan bool
	onWatch     bool
}

// Settings is the main struct for the configuration
type Settings[C any] struct {
	files  fileBackend
	stream streamBackend
	config C
	errors []error
	sync.Mutex
	mnemonic      string
	importCounter int
	hooks         struct {
		change []EventHook
	}

	fileWatch fileWatch
}

func (s *Settings[C]) initDefaults() *Settings[C] {

	errorCount := len(s.errors)
	defer func() {
		if len(s.errors) > errorCount {
			s.notifyErrorHooks()
		}
	}()

	err := runOnTags(&s.config, []string{"default"}, func(v string, field reflect.Value) {

		if field.CanSet() {
			switch field.Kind() {
			case reflect.String:
				field.SetString(v)
			case reflect.Int:
				intVar, err := strconv.Atoi(v)
				if err != nil {
					s.errors = append(s.errors, err)
					return
				}
				field.SetInt(int64(intVar))
			case reflect.Bool:
				field.SetBool(v == "true")
			default:
				s.errors = append(s.errors, newUnsupportedTypeError(field.Type()))
			}

		}
	})

	if err != nil {
		s.errors = append(s.errors, err)
	}

	return s
}

func validateConfig[C any](config C) error {
	t := reflect.TypeOf(config)
	if t.Kind() != reflect.Struct {
		return newUnsupportedTypeError(t)
	}
	return nil
}