package rules;

import static org.codelutin.i18n.I18n._;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import scripts.GravityModel;
import scripts.ResultName;
import scripts.SiMatrix;

import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.io.File;
import java.io.Writer;
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.FileReader;

import org.codelutin.math.matrix.*;

import fr.ifremer.isisfish.simulator.SimulationContext;
import fr.ifremer.isisfish.types.Date;
import fr.ifremer.isisfish.types.Month;
import fr.ifremer.isisfish.entities.*;
import fr.ifremer.isisfish.rule.AbstractRule;
import fr.ifremer.isisfish.datastore.ResultStorage;

import org.codelutin.util.FileUtil;

/**
 * GraviteVPUE1Anchois.java
 *
 * Created: 26 aout 2008
 *
 * @author anonymous <anonymous@labs.libre-entreprise.org>
 * @version $Revision: 1.2 $
 *
 * Last update: $Date: 2007-07-18 08:59:38 $
 * by : $Author: 2SY- Sigrid+Youen+Stephanie $
 */
public class Effort_2000_2004_Anchois extends AbstractRule {
    /** to use log facility, just put in your code: log.info("..."); */
    static private Log log = LogFactory.getLog(Effort_2000_2004_Anchois.class);

	// fichiers rangés dans le répertoire de lancement d'ISIS (la ou se trouve le go) dans rep EffortObs/
	// fichiers métiers x date
	public String param_nomfichier_EffortBolBretons = "EffortObs/EffortBolBretons.csv";//yv
	public String param_nomfichier_EffortBolBasques = "EffortObs/EffortBolBasques.csv";//yv
	public String param_nomfichier_EffortPelProfil1 = "EffortObs/EffortPelProf1.csv";//yv
	public String param_nomfichier_EffortPelProfil2 = "EffortObs/EffortPelProf2.csv";//yv
	public String param_nomfichier_EffortSpanish = "EffortObs/EffortSpanish.csv";
	//public String param_nomfichier_Inactivity = "EffortObs/Inactivity.csv";
	
	protected File EffortBolBretons;
	protected File EffortBolBasques;
	protected File EffortPelProfil1;
	protected File EffortPelProfil2;
	protected File EffortSpanish;
	//protected File Inactivity;
	
	protected List<Metier> metiers;
	protected List<Strategy> strs ;
	// interdit de faire des set sur les strategies de la map, il faut recuperer les strategies de la date courante
	protected Map<String , Strategy> mesStrategies;
	
    protected MatrixND matEffortBolBretons;
	protected MatrixND matEffortBolBasques;
	protected MatrixND matEffortPelProfil1;
	protected MatrixND matEffortPelProfil2;
	protected MatrixND matEffortSpanish;
	//protected MatrixND matInactivity;

    public String [] necessaryResult = {
    };

    public String[] getNecessaryResult() {
        return this.necessaryResult;
    }

    /**
     * Permet d'afficher a l'utilisateur une aide sur la regle.
     * @return L'aide ou la description de la regle
     */
    public String getDescription() throws Exception {
        return _("Chaque annee et mois les efforts observés sont simulés");
		 
    }
     
     /**
     * Appelé au démarrage de la simulation, cette méthode permet d'initialiser
     * des valeurs
     * @param simulation La simulation pour lequel on utilise cette regle
     */
    public void init(SimulationContext context) throws Exception {
        
		// reccuperation des metiers et strategies
		SiMatrix siMatrix = SiMatrix.getSiMatrix(context);
		
		Date date = new Date(0);
        List<Date> dates = new ArrayList <Date>();
		for (int i=1; i < 60; i++) {
		dates.add(new Date (i));
		}
        List<Strategy> strs = siMatrix.getStrategies(date);
        List<Metier> metiers = siMatrix.getMetiers(date);
        List<Month> months = Arrays.asList(Month.MONTH);
 
		// creation de mes strategies
		mesStrategies = new HashMap<String, Strategy>();
		for(Strategy str : strs) {
			mesStrategies.put(str.getName(), str);
		}
		
		System.out.println("strs dans init :" + strs);
		System.out.println("mesStrategies dans init :" + mesStrategies);
 
		// load fishing efforts in a matrix for each strategy
		if (param_nomfichier_EffortBolBretons==null || "".equals(param_nomfichier_EffortBolBretons)){
    		EffortBolBretons = FileUtil.getFile(".*.csv", "fichier 0 csv séparateur ';'");
			EffortBolBasques = FileUtil.getFile(".*.csv", "fichier 1 csv séparateur ';'");
			EffortPelProfil1 = FileUtil.getFile(".*.csv", "fichier 2 csv séparateur ';'");
			EffortPelProfil2 = FileUtil.getFile(".*.csv", "fichier 3 csv séparateur ';'");
			EffortSpanish = FileUtil.getFile(".*.csv", "fichier 4 csv séparateur ';'");
			//Inactivity = FileUtil.getFile(".*.csv", "fichier 5 csv séparateur ';'");
    	} else {
    		EffortBolBretons = new File(param_nomfichier_EffortBolBretons);
			EffortBolBasques = new File(param_nomfichier_EffortBolBasques);
			EffortPelProfil1 = new File(param_nomfichier_EffortPelProfil1);
			EffortPelProfil2 = new File(param_nomfichier_EffortPelProfil2);
			EffortSpanish = new File(param_nomfichier_EffortSpanish);
			//Inactivity = new File(param_nomfichier_Inactivity);
			
    	}


		matEffortBolBretons = MatrixFactory.getInstance().create(
				"matEffortBolBretons",
				new List[]{metiers,dates},
                new String[]{"Metiers","Date"});
		matEffortBolBasques = MatrixFactory.getInstance().create(
				"matEffortBolBasques",
				new List[]{metiers,dates},
                new String[]{"Metiers","Date"});
		matEffortPelProfil1 = MatrixFactory.getInstance().create(
				"matEffortPelProfil1",
				new List[]{metiers,dates},
                new String[]{"Metiers","Date"});
		matEffortPelProfil2 = MatrixFactory.getInstance().create(
				"matEffortPelProfil2",
				new List[]{metiers,dates},
                new String[]{"Metiers","Date"});
		matEffortSpanish = MatrixFactory.getInstance().create(
				"matEffortSpanish",
				new List[]{metiers,dates},
                new String[]{"Metiers","Date"});
		/*matInactivity = MatrixFactory.getInstance().create(
				"matInactivity",
				new List[]{strs,dates},
                new String[]{"Strategies","Date"});*/
        
		matEffortBolBretons.importCSV(new FileReader(EffortBolBretons),new int []{0,0});
		matEffortBolBasques.importCSV(new FileReader(EffortBolBasques),new int []{0,0});
		matEffortPelProfil1.importCSV(new FileReader(EffortPelProfil1),new int []{0,0});
		matEffortPelProfil2.importCSV(new FileReader(EffortPelProfil2),new int []{0,0});
		matEffortSpanish.importCSV(new FileReader(EffortSpanish),new int []{0,0});
		//matInactivity.importCSV(new FileReader(Inactivity),new int []{0,0});
        System.out.println("Chargement de matrice matEffortBolBretons" + matEffortBolBretons);
		System.out.println("Chargement de matrice matEffortBolBasques" + matEffortBolBasques);
		System.out.println("Chargement de matrice matEffortPelProfil1" + matEffortPelProfil1);
		System.out.println("Chargement de matrice matEffortPelProfil2" + matEffortPelProfil2);
		System.out.println("Chargement de matrice matEffortSpanish" + matEffortSpanish);
		//System.out.println("Chargement de matrice matInactivity" + matInactivity);
        
    }// fin de init
    /**
     * La condition qui doit etre vrai pour faire les actions
     * @param simulation La simulation pour lequel on utilise cette regle
     * @return vrai si on souhaite que les actions soit faites
     */ 
    public boolean condition(SimulationContext context, Date date, Metier metier) throws Exception {
        return true;
    }
 
    /**
     * Si la condition est vrai alors cette action est executée avant le pas
     * de temps de la simulation.
     * @param simulation La simulation pour lequel on utilise cette regle
     */
	// Booleen permettant que ne boucler que sur un seul metier dans la preaction :
	boolean first = true;
    public void preAction(SimulationContext context, Date date, Metier metier) throws Exception {        
			if (log.isDebugEnabled()) {
             	log.debug("first = "+ first + "date:"+ date);
   			}
			System.out.println("first = " + first+ " ,on passe dans la preaction ?");
			if (first){ // on passe dans preaction pour la premiere fois
				System.out.println("Oui, preaction : ");
				double newProp=0;
				//int newInactivity = 0;
				
				// Boucle sur les strategies 
				//System.out.println("strs dans preaction : " + strs);
				System.out.println("mesStrategies : " + mesStrategies);
				
				List<Strategy> mStr = new ArrayList(mesStrategies.values());
				//for(Strategy strIndex : strs){
				for(Strategy strIndex : mStr){
					// interdit de faire des set sur les strategies de la semantique de la matrice, il faut recuperer les strategies de la date courante
					Strategy str = (Strategy)context.getDB().findByTopiaId(strIndex.getTopiaId());
					StrategyMonthInfo smi = str.getStrategyMonthInfo(date.getMonth());
					
					System.out.println("pour str="+str.getName());
					
					/*newInactivity = (int) matInactivity.getValue(str,date.getDate());
					smi.setMinInactivityDays(newInactivity);
					System.out.println("pour la strategy=" + str.getName() +", l'année : "+ date.getYear() + " et le mois = "+date.getMonth()+": newInactivity= "+ newInactivity);
					*/
					// on boucle sur les metiers de la strategie pour initialiser les efforts avec matEffort
					Collection<EffortDescription> strMet = str.getSetOfVessels().getPossibleMetiers() ;
					for (EffortDescription ed : strMet){ 
						Metier strMetier = ed.getPossibleMetiers();
       				    System.out.println("pour le metier=" + strMetier);
						if (str.getName().equals("BolBretons")){
							newProp = matEffortBolBretons.getValue(strMetier,date.getDate());
						} else if (str.getName().equals("BolBasques")){
							newProp = matEffortBolBasques.getValue(strMetier,date.getDate());
						} else if (str.getName().equals("PelProfil1")){
							newProp = matEffortPelProfil1.getValue(strMetier,date.getDate());
						} else if (str.getName().equals("PelProfil2")){
							newProp = matEffortPelProfil2.getValue(strMetier,date.getDate());
						} else if (str.getName().equals("Espagnols")){
							newProp = matEffortSpanish.getValue(strMetier,date.getDate());
						}
						System.out.println("pour le metier=" + strMetier +" l'année : "+ date.getYear() + "et le mois = "+date.getMonth()+" newProp= "+ newProp);
					    smi.setProportionMetier(strMetier,newProp);
						
					}
				}//fin de boucle sur strategies
				first = false;	 
			}// fin de first= true
 	        if (log.isDebugEnabled()) {
        	    log.debug("fin Effort Anchois Action avant");
       		 }
    }// fin de pre action
 
    /**
     * Si la condition est vrai alors cette action est strategy=" + str.getName() +", l'année : "+ date.getYear() + " et le mois = "+date.getMonth()+": newInactivity= "+ newInactivity);
					
					// on boucle sur les metiers de la strategie pour initialiser les efforts avec matEffort
					Collection<EffortDescription> strMet = str.getSetOfVessels().getPossibleMetiers() ;
					for (EffortDescription ed : strMet){ 
						Metier strMetier = ed.getPossibleMetiers();
       				    System.out.println("pour le metier=" + strMetier);
executée apres le pas
     * de temps de la simulation.
     * @param simulation La simulation pour lequel on utilise cette regle
     */
    public void postAction(SimulationContext context, Date date, Metier metier) throws Exception {
    first = true;    
    }

}
