package config

import (
	"fmt"
	"io/ioutil"
	"strings"

	yaml "gopkg.in/yaml.v2"
)

const (
	LOG_LEVEL_OFF = iota
	LOG_LEVEL_INFO
	LOG_LEVEL_DEBUG
)

type ConfigT struct {

	// Domain

	Url    string
	Domain string

	// Logging

	LogLevel int `yaml:"log_level"`

	// Secret keys

	Keys struct {
		CookieStoreKey string `yaml:"cookie_store_key"`
		JWTSigningKey  string `yaml:"jwt_signing_key"`
	}

	// Admin credentials

	Admin struct {
		Username string
		Password string
	}

	// Database

	Orm struct {
		Connection  string
		Options     string
		Reset       bool
		AutoMigrate bool
		Regenerate  bool
	}

	Ldap struct {
		Host string

		AdminCN       string `yaml:"admin_cn"`
		AdminPassword string `yaml:"admin_password"`

		TeachersDN string `yaml:"teachers_dn"`
		PeopleDN   string `yaml:"people_dn"`
		GroupsDN   string `yaml:"groups_dn"`

		MailGIDNumber  string `yaml:"mail_gid_number"`
		FirstUIDNumber string `yaml:"first_uid_number"`

		MailDirBasePath string `yaml:"maildir_base_path"`
		MailQuota       string `yaml:"mail_quota"`
	}

	Cloud struct {
		Url      string
		Username string
		Password string
	}

	Smtp struct {
		Host     string
		Port     int
		Username string
		Password string
		From     string
		Cc       string
	}

	Sync struct {
		Schedule string
		SendMail bool `yaml:"send_mail"`
		SafeRun  bool `yaml:"safe_run"`
		Verbose  bool

		TeachersSearchBase        string `yaml:"teachers_search_base"`
		AdministrativesSearchBase string `yaml:"administratives_search_base"`

		TeachersGroup        string `yaml:"teachers_group"`
		AdministrativesGroup string `yaml:"administratives_group"`

		TeachersML string `yaml:"teachers_ml"`

		DepartmentsCoordinatorsGroup string `yaml:"departments_coordinators_group"`
		DepartmentsCoordinatorsML    string `yaml:"departments_coordinators_ml"`
	}

	Documents struct {
		OutputPath string `yaml:"output_path"`
	}
}

var (
	Config *ConfigT
)

func init() {
	Config = new(ConfigT)
}

// ReadFile reads the config file placed at the given path.
func ReadFile(path string, config *ConfigT) error {
	cf, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}
	if err := yaml.Unmarshal(cf, config); err != nil {
		return err
	}
	return nil
}

// Read reads the config data from the given slice.
func Read(data []byte, config *ConfigT) error {
	if err := yaml.Unmarshal(data, config); err != nil {
		return err
	}
	return nil
}

func (conf *ConfigT) DomainDN() (out string) {
	for _, dc := range strings.Split(conf.Domain, ".") {
		out += "dc=" + dc + ","
	}
	return strings.TrimRight(out, ",")
}

func (conf *ConfigT) AdminCN() string {
	return fmt.Sprintf("cn=%s,%s", conf.Ldap.AdminCN, conf.DomainDN())
}
