package config

import (
	"io"
	"os"

	"github.com/pkg/errors"
	"gopkg.in/yaml.v3"
)

// Config definition
type Config struct {
	Admin        AdminServerConfig  `yaml:"admin"`
	Proxy        ProxyServerConfig  `yaml:"proxy"`
	Redis        RedisConfig        `yaml:"redis"`
	Logger       LoggerConfig       `yaml:"logger"`
	Layers       LayersConfig       `yaml:"layers"`
	Bootstrap    BootstrapConfig    `yaml:"bootstrap"`
	Integrations IntegrationsConfig `yaml:"integrations"`
}

// NewFromFile retrieves the configuration from the given file
func NewFromFile(path string) (*Config, error) {
	config := NewDefault()

	data, err := os.ReadFile(path)
	if err != nil {
		return nil, errors.Wrapf(err, "could not read file '%s'", path)
	}

	if err := yaml.Unmarshal(data, config); err != nil {
		return nil, errors.Wrapf(err, "could not unmarshal configuration")
	}

	return config, nil
}

// NewDumpDefault dump the new default configuration
func NewDumpDefault() *Config {
	config := NewDefault()

	return config
}

// NewDefault return new default configuration
func NewDefault() *Config {
	return &Config{
		Admin:        NewDefaultAdminServerConfig(),
		Proxy:        NewDefaultProxyServerConfig(),
		Logger:       NewDefaultLoggerConfig(),
		Redis:        NewDefaultRedisConfig(),
		Layers:       NewDefaultLayersConfig(),
		Bootstrap:    NewDefaultBootstrapConfig(),
		Integrations: NewDefaultIntegrationsConfig(),
	}
}

// Dump the given configuration in the given writer
func Dump(config *Config, w io.Writer) error {
	data, err := yaml.Marshal(config)
	if err != nil {
		return errors.Wrap(err, "could not dump config")
	}

	if _, err := w.Write(data); err != nil {
		return errors.WithStack(err)
	}

	return nil
}