package main

import (
  "encoding/json"
  "errors"
  "os"
  "path"
  "slices"
  "strings"

  "github.com/charmbracelet/log"
)

type Config struct {
  UserName     string
  UserID       string
  ClientID     string
  ClientSecret string
}

// Finds a valid configuration file if it exists.  If nil is returned one
// should be created.
func find_config() (string, error) {
  // Paths where a tremble.conf file might reside
  // TODO: Check XDG_CONFIG_DIRS last in case XDG_CONFIG_HOME isn't set.
  var paths []string = []string{
    ".",
    "$XDG_CONFIG_HOME/tremble",
    "$HOME/.tremble",
    "$HOME/.config/tremble",
  }

  if configDirs, isSet := os.LookupEnv("XDG_CONFIG_DIRS"); isSet {
  	paths = slices.Concat(paths, strings.Split(configDirs, ":"))
  }

  for _, p := range paths {
    dir := os.ExpandEnv(p)
    pstr := path.Join(dir, "tremble.conf")

    _, err := os.Lstat(pstr)
    if err != nil {
      continue
    }
    return pstr, nil
  }

  return "", errors.New("No config file found.")
}

// Finds a configuration file and processes it if one exists.
func read_config() (*Config, error) {
  pstr, err := find_config()
  if err != nil {
    log.Info(err)
    return nil, err
  }

  cdata, err := os.ReadFile(pstr)
  if err != nil {
    log.Info(err)
    return nil, err
  }

  // Parse the file and return.
  var confOut Config
  err = json.Unmarshal(cdata, &confOut)
  if err != nil {
    return nil, err
  }

  return &confOut, nil
}

// Writes configuration to the tremble config file.  Currently this overwrites
// the entire thing if found, or creates a new one if not.
func write_config(config *Config) error {
  var pstr string

  // XXX: Maybe check to make sure this isn't some substantial error.
  // XXX: Some duplication here.
  pstr, err := find_config()
  if err != nil {
    // Get XDG_CONFIG_HOME, fallback to $HOME/.config
    configHome := os.Getenv("XDG_CONFIG_HOME")
    if configHome == "" {
      home := os.Getenv("HOME")
      if home == "" {
        log.Fatal("Cannot determine config directory: HOME not set")
      }
      configHome = path.Join(home, ".config")
    }

    dir := path.Join(configHome, "tremble")
    if err := os.MkdirAll(dir, 0755); err != nil {
      log.Fatalf("Couldnt create directory '%v': %v\n", dir, err)
    }

    pstr = path.Join(dir, "tremble.conf")
  }

  // TODO: Make this fatal in the caller, or... not.  Just not here.
  cdata, err := json.Marshal(config)
  if err != nil {
    log.Fatalf("Couldn't write config %v: %v\n", config, err)
  }

  err = os.WriteFile(pstr, cdata, 0755)
  if err != nil {
    log.Fatalf("Couldn't write config %v: %v\n", config, err)
  }

  return nil
}
