package server

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"strings"
)

// Config embodies the configuration for a game. These are populated in various
// ways (json POSTed to server, config file, constants) and are typically owned
// by a Controller.
type Config struct {
	Tick          int        `json:"tick"` // ms
	Timescale     float64    `json:"timescale"`
	Delta         float64    `json:"delta"`
	Width         int        `json:"width"`
	Height        int        `json:"height"`
	ObstacleCount int        `json:"obstacle_count"`
	Obstacles     []Obstacle `json:'obstacles'`
	MaxPoints     int        `json:"max_points"`
	Mode          string     `json:"mode"`
}

const (
	TICK           = 60  // ms, this is how often physics is updated
	TIMESCALE      = 1.0 // this tweaks the temporal duration of a TICK
	WIDTH          = 800
	HEIGHT         = 550
	OBSTACLE_COUNT = 5
	MAX_POINTS     = 500 // allowing for 50 pts in every category
	DEFAULT_MODE   = "deathmatch"
)

// LoadConfig takes the location of a json file that contains values desired to
// be used in the creation of games. Priority is given to values specified at
// game cration time using control channel, followed by values in config file,
// followed by constants defined above.
func LoadConfig(filename string) (Config, error) {
	c := Config{
		Tick:          TICK,
		Timescale:     TIMESCALE,
		Width:         WIDTH,
		Height:        HEIGHT,
		ObstacleCount: OBSTACLE_COUNT,
		MaxPoints:     MAX_POINTS,
		Mode:          DEFAULT_MODE,
	}
	home := os.Getenv("HOME")
	if len(filename) > 1 && filename[:2] == "~/" {
		filename = strings.Replace(filename, "~", home, 1)
	}
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		log.Printf("%+v not found, using defaults", filename)
	} else {
		log.Printf("found config file: %s", filename)
		f, err := ioutil.ReadFile(filename)
		if err != nil {
			return c, err
		}
		err = json.Unmarshal(f, &c)
		if err != nil {
			return c, errors.New(fmt.Sprintf("config parse error: %s", err))
		}
	}
	c.Delta = float64(c.Tick) / 1000.0 * c.Timescale
	log.Printf("final config: %#v", c)
	return c, nil
}
