package config

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"

	"git.kirsle.net/apps/gosocial/pkg/log"
)

// Current loaded settings.json
var Current = DefaultVariable()

// Variable configuration attributes (loaded from settings.json).
type Variable struct {
	BaseURL    string
	AdminEmail string
	Mail       Mail
	Redis      Redis
	Database   Database
}

// DefaultVariable returns the default settings.json data.
func DefaultVariable() Variable {
	return Variable{
		BaseURL: "http://localhost:8080",
		Mail: Mail{
			Enabled: false,
			Host:    "localhost",
			Port:    25,
			From:    "no-reply@localhost",
		},
		Redis: Redis{
			Host: "localhost",
			Port: 6379,
		},
		Database: Database{
			SQLite:   "database.sqlite",
			Postgres: "host=localhost user=gosocial password=gosocial dbname=gosocial port=5679 sslmode=disable TimeZone=America/Los_Angeles",
		},
	}
}

// LoadSettings loads the settings.json file or, if not existing, creates it with the default settings.
func LoadSettings() {
	if _, err := os.Stat(SettingsPath); !os.IsNotExist(err) {
		log.Info("Loading settings from %s", SettingsPath)
		content, err := ioutil.ReadFile(SettingsPath)
		if err != nil {
			panic(fmt.Sprintf("LoadSettings: couldn't read settings.json: %s", err))
		}

		var v Variable
		err = json.Unmarshal(content, &v)
		if err != nil {
			panic(fmt.Sprintf("LoadSettings: couldn't parse settings.json: %s", err))
		}

		Current = v
	} else {
		var buf bytes.Buffer
		enc := json.NewEncoder(&buf)
		enc.SetIndent("", "    ")
		err := enc.Encode(DefaultVariable())
		if err != nil {
			panic(fmt.Sprintf("LoadSettings: couldn't marshal default settings: %s", err))
		}

		ioutil.WriteFile(SettingsPath, buf.Bytes(), 0600)
		log.Warn("NOTICE: Created default settings.json file - review it and configure mail servers and database!")
	}

	// If there is no DB configured, exit now.
	if !Current.Database.IsSQLite && !Current.Database.IsPostgres {
		log.Error("No database configured in settings.json. Choose SQLite or Postgres and update the DB connector string!")
		os.Exit(1)
	}
}

// Mail settings.
type Mail struct {
	Enabled  bool
	Host     string // localhost
	Port     int    // 25
	From     string // noreply@localhost
	Username string // SMTP credentials
	Password string
}

// Redis settings.
type Redis struct {
	Host string
	Port int
	DB   int
}

// Database settings.
type Database struct {
	IsSQLite   bool
	IsPostgres bool
	SQLite     string
	Postgres   string
}
