package rules;

import java.io.*;
import java.util.regex.Pattern;

import org.nuiton.math.matrix.*;

import fr.ifremer.isisfish.simulator.SimulationContext;
import fr.ifremer.isisfish.rule.AbstractRule;
import fr.ifremer.isisfish.annotations.Doc;
import fr.ifremer.isisfish.entities.*;
import fr.ifremer.isisfish.types.*;

import static scripts.PTAtoolbox.expandEnvirVar;

/**
 * lors présimul: changer q
 *
 * Auteure: LEFORESTIER Sophie, 2018
 * Dernière modif: PHAN Tuan Anh, 2022:
 *   - ajouter la fonctionnalité qui permet de d’utiliser les variables d’environnement,
 *     (il faut être accompagné du script PTAtoolbox)
 *   - on n’est plus obligé d’exclure underscore _ dans le nom de simulation
 */
public class ChgmtQ_variable extends AbstractRule {

	@Doc("README")
	public String param_README = String.join(" ►►► ",
		"auteure: LEFORESTIER Sophie, 2018",
		"dernière modif: PHAN Tuan Anh, 2022"
	);

	@Doc("Path")
	public String param_path = "${PBS_O_WORKDIR}/RUN";

	public String[] necessaryResult = {}; // must be initialized, error if not
	public String[] getNecessaryResult() { return this.necessaryResult; }

	/** Permet d’afficher à l’utilisateur une aide sur la règle */
	public String getDescription() { return "Change capturability parameters from a matrix"; }

	/**
	 * Appelé au démarrage de la simulation, cette méthode permet d’initialiser des valeurs.
	 *
	 * @param context la simulation pour lequel on utilise cette règle
	 */
	public void init(SimulationContext context) throws Exception {
		String simu = context.getSimulationControl().getId();
		// String simu = "simu_i0";
		System.out.println("nom de la simu en cours : " + simu);

		Pattern simulNamePattern = Pattern.compile("^(.+)_(i\\d+)$");
		String path = simulNamePattern.matcher(simu).replaceAll("_$1/$2/q.csv");
		// exemple : "simu_i0" devient "RUN_simu/i0/q.csv"

		param_path = expandEnvirVar.replace(param_path);
		File Accessibility = new File(param_path + path);
		MatrixND matAccessibility = MatrixFactory.getInstance().create(Accessibility);
		System.out.println("matrice importée " + matAccessibility);

		for (Population pop : context.getSimulationStorage().getParameter().getPopulations()) {
			// pop = (Population) context.getDB().findByTopiaId(pop.getTopiaId()); // récupère population ciblée
			MatrixND c = pop.getCapturability();
			System.out.println("ancienne matrice " + pop + c);
			for (MatrixIterator i = c.iterator(); i.hasNext();) {
				i.next();
				PopulationGroup group = (PopulationGroup) i.getSemanticsCoordinates()[0];
				double q = matAccessibility.getValue(group.getId());
				i.setValue(q);
			}
			System.out.println("Nouvelle matrice " + pop + c);
		}
	}

	/**
	 * La condition qui doit être vraie pour faire les actions.
	 *
	 * @param context la simulation pour laquelle on utilise cette règle
	 * @param step le pas de temps courant
	 * @param metier le métier concerné
	 * @return vrai si on souhaite que les actions soit faites
	 */
	public boolean condition(SimulationContext context, TimeStep step, Metier metier) {
		// on va afficher matrice accessibilité pour assurer que la règle marche bien
		return true;
	}

	/** Si la condition est vraie alors cette action est exécutée avant le pas de temps de la simulation. */
	public void preAction(SimulationContext context, TimeStep step, Metier metier) {
		for (Population pop : context.getSimulationStorage().getParameter().getPopulations()) {
			MatrixND c = pop.getCapturability();
			System.out.println("accessibilité " + pop + c);
		}
	}

	/** Si la condition est vraie alors cette action est exécutée après le pas de temps de la simulation. */
	public void postAction(SimulationContext context, TimeStep step, Metier metier) {}

}
