package configuration

import (
	"encoding/json"
	"log"
	"os"
)

// Configuration définit les élèments de la configuration
// du jeu. Pour ajouter un élèment de configuration il
// suffit d'ajouter un champs dans cette structure.
//
// Les champs directement lus dans le fichier de configuration sont :
//   - DebugMode : indique si on est en mode debug ou pas
//   - NumTileX, NumTileY : les nombres de cases affichées à l'écran
//     en largeur et hauteur.
//   - TileSize : la taille en pixels du côté d'une case.
//   - NumCharacterAnimImages : le nombre de d'images de l'animation du
//     personnage.
//   - NumFramePerCharacterAnimImage : le nombre d'appels à update ou
//     de 1/60 de seconde) qui ont lieu entre deux images de l'animation
//     du personnage.
//   - NumTileForDebug : le nombre de cases à ajouter à droite de l'écran
//     pour afficher les informations de debug
//   - CameraMode : le type de caméra à utiliser (0 pour une caméra fixe
//     et 1 pour une caméra qui suit le personnage).
//   - FloorKind : détermine la méthode à utiliser pour afficher le terrain
//     (quadrillage, lecture dans un fichier, quadtree, etc)
//   - FloorFile : le chemin d'un fichier où lire les informations sur le
//     terrain si nécessaire
//
// Les champs calculés à partir des précédents sont :
//   - ScreenWidth, ScreenHeight : la largeur et la hauteur de l'écran
//     en pixels (hors zone d'affichage pour le debug)
//   - ScreenCenterTileX, ScreenCenterTileY : les coordonnées de la case
//     au centre de l'écran, où sera placé la caméra.
//
// Les champs permettant l'activation des extensions ne sont utilisables
// qu'avec FloorKind = 2, à l'exception des extensions 5 et 6 prévues aussi
// pour FloorKind = 1. Ces champs sont :
//
//   - Extension1 : génération d'un terrain aléatoire.
//   - Extension1_dimensions : dimensions du terrain aléatoire.
//   - Extension2 : sauvegarde du terrain précédemment généré dans un fichier
//     placé dans le dossier floor-files.
//   - Extension2_nameFile : le nom dudit fichier. Si ce fichier existe déjà
//     dans le dossier floor-files, le fichier préexistant est écrasé.
//   - Extension3 : animation des décors (eau et herbe).
//   - Extension4 : ajout de la téléportation (mode d'emploi : placez vos
//     téléporteurs avec la touche t - jusqu'à 2 en simultané - puis
//     positionnez-vous sur l'un pour apparaître sur l'autre.)
//   - Extension5 : impossibilité de marcher sur l'eau (décale le personnage
//     à la génération du monde si nécessaire, voire modifie la tuile de départ
//     si toutes les cases sont d'eau)
//   - Extension6 : bloque la caméra quand celle-ci atteint les bords du
//     terrain afin de ne pas apercevoir le vide hors du terrain
//   - Extension11 : répétition du terrain quand ses limites sont atteintes,
//     procurant l'effet d'un monde rond (possible de s'y déplacer à l'infini)
//   - Extension12 : zoom / dézoom du terrain (mode d'emploi : zoomez avec la
//     touche e jusqu'à obtenir un terrain de côtés 3x3 au minimum ; dézoomez avec
//     la touche r jusqu'à ce que l'ensemble du terrain puisse être contenu dans
//     l'écran ou que l'écran affiche 50 tuiles de côtés au maximum ; il n'est pas
//     possible de se déplacer tout en zoomant / dézoomant pour des raisons d'esthétisme).
//
// Notes complémentaires :
//   - Les extensions 6 et 11 étant naturellement incompatibles (6 : bloque sur
//     bords ; 11 : répète indéfiniment), les effets de l'extension 6 seront
//     nuls si les deux sont activées
//   - Les extensions 11 et 12 sont partiellement incompatibles (en cas de problème
//     d'affichage en bas de l'écran, veuillez rezoomer et dézoomer légèrement
//     pour corriger le problème)
type Configuration struct {
	DebugMode                     bool
	NumTileX, NumTileY            int
	TileSize                      int
	NumCharacterAnimImages        int
	NumFramePerCharacterAnimImage int
	NumTileForDebug               int
	CameraMode                    int
	FloorKind                     int
	FloorFile                     string
	Extension1                    bool
	Extension1_dimensions         []int
	Extension2                    bool
	Extension2_nameFile           string
	Extension3                    bool
	Extension4                    bool
	Extension5                    bool
	Extension6                    bool
	Extension11                   bool
	Extension12                   bool

	ScreenWidth, ScreenHeight            int `json:"-"`
	ScreenCenterTileX, ScreenCenterTileY int `json:"-"`
}

// Global est la variable qui contient la configuration
// du jeu. Sa valeur est fixée à partir de la lecture d'un
// fichier de configuration par la fonction Load. C'est
// cette variable qu'il faut lire (configuration.Global)
// pour accéder à la configuration depuis d'autres paquets.
var Global Configuration

// Load se charge de lire un fichier de configuration, de
// remplir les champs obtenus par simple lecture, puis
// d'appeler la fonction qui remplit les champs calculés.
func Load(configurationFileName string) {
	content, err := os.ReadFile(configurationFileName)
	if err != nil {
		log.Fatal("Error while opening configuration file: ", err)
	}

	err = json.Unmarshal(content, &Global)
	if err != nil {
		log.Fatal("Error while reading configuration file: ", err)
	}

	setComputedFields()
}

// setComputedFields se charge de remplir les champs calculés
// de la configuration à partir des autres champs.
func setComputedFields() {
	Global.ScreenWidth = Global.NumTileX * Global.TileSize
	Global.ScreenHeight = Global.NumTileY * Global.TileSize
	Global.ScreenCenterTileX = Global.NumTileX / 2
	Global.ScreenCenterTileY = Global.NumTileY / 2
}
