package boilerplate

import (
	"fmt"
	"io/ioutil"

	"github.com/go-yaml/yaml"
	"github.com/pkg/errors"
)

const (
	DefaultConfigFileName = ".boilerplate.yaml"
)

type ConfigFileGoConfig struct {
	Binary     bool   // normally autodetected; specify true to force fetching a tag by name even it matches something we know how to get binaries for
	Version    string `yaml:",omitempty"` // required
	Repository string `yaml:",omitempty"`
	Primary    bool   `yaml:",omitempty"` // omit-on-false
}

type ConfigFile struct {
	Project struct {
		Type string // one of {'library', 'daemon', 'utility'}; TODO: what about multiple build products?
		Name string `yaml:",omitempty"`
	}
	Golang struct {
		Configurations []*ConfigFileGoConfig

		Linters struct {
			Golint struct {
				Enabled          bool
				ExcludeGenerated bool `yaml:"exclude_generated"` // right now, '*.pb.go'
			}
			Errcheck struct {
				IgnoreTests bool `yaml:"ignore_tests"`
			}
		}
	}
	Jenkins struct {
		JobName string `yaml:",omitempty"`
	}
	Courier struct {
		// Enabled    bool   // default to true for daemons and false otherwise?
		DeployPath string `yaml:"deploy_path,omitempty"` // required if courier is enabled
	}
}

func LoadConfigFile(configPath string) (*ConfigFile, error) {
	fileContents, err := ioutil.ReadFile(configPath)
	if err != nil {
		return nil, errors.Wrap(err, fmt.Sprintf("failed to read configuration file: %s", configPath))
	}

	config := &ConfigFile{}
	config.Golang.Linters.Golint.Enabled = true
	config.Golang.Linters.Golint.ExcludeGenerated = true

	if err := yaml.Unmarshal(fileContents, config); err != nil {
		// TODO: Print nicer-looking type errors if appropriate.
		// TODO: This does *not* return an error if there are extra, undefined keys present! That's horrible.
		return nil, errors.Wrap(err, "failed to unmarshal configuration")
	}

	return config, nil
}
