package fr.monlouyan.bakefile;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Moteur principal de l'application Bake.
 * Cette classe est responsable de l'orchestration du processus de build
 * en utilisant les règles définies dans le fichier Bakefile.
 * 
 * @author Moncef STITI, Yanis HAMOUDI, Louay DARDOURI
 * @version 1.0
 */
public class BakeEngine {

	/** Analyseur syntaxique du fichier Bakefile */
    private BakefileParser parser;

	/** Responsable de la résolution des dépendances entre règles */
    private DependencyResolver resolver;

	/** Exécuteur des commandes définies dans les règles */
    private CommandExecutor executor;

	/** Map qui stocke toutes les règles indexées par leur nom */
    private static Map<String, Rule> ruleMap;
    
	/**
     * Constructeur qui initialise le moteur Bake.
     * Crée un parser pour le fichier "Bakefile" par défaut et initialise le résolveur de dépendances.
     */
    public BakeEngine() {
        this.parser = new BakefileParser("Bakefile");
        this.resolver = new DependencyResolver(BakeCLI.isDebug());
        ruleMap = new HashMap<>();
    }

	/**
     * Vérifie si une règle avec le nom spécifié existe.
     * 
     * @param target Nom de la règle à vérifier
     * @return true si la règle existe, false sinon
     */
    public static boolean hasRule(String target) {
        return ruleMap.containsKey(target);
    }


	/**
     * Récupère une règle par son nom.
     * 
     * @param target Nom de la règle à récupérer
     * @return La règle correspondante ou null si elle n'existe pas
     */
    public static Rule getRule(String target) {
        return ruleMap.get(target);
    }
    
	/**
     * Exécute le processus de build complet.
     * Cette méthode réalise les étapes suivantes :
     * <ol>
     *   <li>Parse le fichier Bakefile</li>
     *   <li>Construit la carte des règles</li>
     *   <li>Résout les dépendances entre les règles</li>
     *   <li>Exécute les règles dans l'ordre déterminé</li>
     * </ol>
     */
    public void run() {
		// Analyse le fichier Bakefile pour extraire les règles
        List<Rule> rules = parser.parse();

		// Ajoute toutes les règles à la map pour référence rapide
        for (Rule rule : rules) {
            ruleMap.put(rule.getName(), rule);
        }

		// Résout les dépendances pour déterminer l'ordre d'exécution
        List<Rule> rulesToBuild = resolver.resolve(rules, BakeCLI.getTargets());
        this.executor = new CommandExecutor(BakeCLI.isDebug(), resolver.isCircular());
		
		// Exécute les règles dans l'ordre déterminé
        for (Rule rule : rulesToBuild) {
            executor.execute(rule);
        }
    }
}