/*
Package config hosts logic to read and parse files in ~/.twitch/ to enable
Go-based twitch subcommands to use that configuration in a standard way.
*/
package config

import (
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"

	"gopkg.in/yaml.v2"

	homedir "github.com/mitchellh/go-homedir"
)

const (
	confDirPath  = ".twitch"
	confFileName = "config.yml"
)

type Config struct {
	Github *GithubConfig
}

type GithubConfig struct {
	Username *string
	Token    *string
}

func New() *Config {
	return &Config{
		Github: &GithubConfig{},
	}
}

func Read() (*Config, error) {
	e, err := Exists()
	if err != nil {
		return nil, err
	}

	if !e {
		return nil, fmt.Errorf("~/%v not found! Run 'twitch configure' to create it.\n", path.Join(confDirPath, confFileName))
	}

	config := &Config{}

	p, err := resolvedPath()
	if err != nil {
		return nil, err
	}

	b, err := ioutil.ReadFile(p)
	if err != nil {
		return nil, err
	}

	err = yaml.Unmarshal(b, config)
	if err != nil {
		return nil, err
	}

	return config, nil
}

func Exists() (bool, error) {
	p, err := prepare()
	if err != nil {
		return false, err
	}

	_, err = os.Stat(p)
	if err == nil {
		return true, nil
	}

	if os.IsNotExist(err) {
		return false, nil
	}

	return true, err
}

func resolvedPath() (string, error) {
	home, err := homedir.Dir()
	if err != nil {
		return "", fmt.Errorf("Could not find home directory: %v", err)
	}

	return path.Join(home, confDirPath, confFileName), nil
}

func prepare() (string, error) {
	p, err := resolvedPath()
	if err != nil {
		return "", err
	}

	dir := filepath.Dir(p)

	_, err = os.Stat(dir)
	if err == nil {
		return p, nil
	}

	if os.IsNotExist(err) {
		err = os.Mkdir(dir, os.ModeDir|0700)
		if err != nil {
			return "", err
		}
	}

	return p, nil
}

func Write(c *Config) error {
	p, err := prepare()
	if err != nil {
		return err
	}

	b, err := yaml.Marshal(c)
	if err != nil {
		return fmt.Errorf("Could not render config file: %v", err)
	}

	f, err := os.Create(p)
	defer func() {
		err := f.Close()
		if err != nil {
			fmt.Fprintf(os.Stderr, "Could not close config file: %v", err)
		}
	}()
	if err != nil {
		return fmt.Errorf("Could not create config file: %v", err)
	}

	_, err = f.Write(b)
	if err != nil {
		return fmt.Errorf("Could not write config file: %v", err)
	}

	return nil
}
