package rules;

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

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.math.matrix.MatrixIterator;
import org.nuiton.math.matrix.MatrixND;
import org.nuiton.math.matrix.*;
import scripts.ResultName;
import scripts.SiMatrix;

import fr.ifremer.isisfish.simulator.MetierMonitor;
import fr.ifremer.isisfish.simulator.SimulationContext;
import fr.ifremer.isisfish.types.TimeStep;
import fr.ifremer.isisfish.types.Month;
import fr.ifremer.isisfish.entities.*;
import fr.ifremer.isisfish.rule.AbstractRule;
import scripts.ResultName;
import scripts.SiMatrix;
import fr.ifremer.isisfish.entities.Metier;
import fr.ifremer.isisfish.entities.Population;
import fr.ifremer.isisfish.entities.PopulationGroup;
import fr.ifremer.isisfish.entities.Species;
import fr.ifremer.isisfish.entities.TargetSpecies;
import fr.ifremer.isisfish.simulator.PopulationMonitor;
import fr.ifremer.isisfish.simulator.SimulationContext;
import fr.ifremer.isisfish.simulator.ResultManager;
import fr.ifremer.isisfish.util.Doc;

/**
 * Cette methode remplace aussi TailleMin pour le Merlu dans PecherieGdG
 * inspire de TailleMIN
 * Created: 30 novembre 2006
 *
 * @author anonymous <anonymous@labs.libre-entreprise.org>
 * @version $Revision: 1.1 $
 *
 * Last update: $Date: 2012 08_28 $
 * by : $Stephanie Mahevas$
 */
public class Ogive_de_Trie_Merlu extends AbstractRule {

    /** to use log facility, just put in your code: log.info("..."); */
    static private Log log = LogFactory.getLog(Ogive_de_Trie_Merlu.class);

   @Doc(value = "Begin step")
    public TimeStep param_beginStep = new TimeStep(0);

    @Doc(value = "End step")
    public TimeStep param_endStep = new TimeStep(119);
	
    @Doc(value = "Affected species")
    public Species param_species = null;

    @Doc(value = "param_Retention_L50")
    public double param_Retention_L50 = 29.4307;

    @Doc(value = "param_Retention_slope")
    public double param_Retention_slope = 2.02485;
	
	@Doc(value = "param_TailleMin")
    public double param_TailleMin = 27;

    @Doc(value = "Proportion de survie")
    public double param_propSurvie = 0;

    public String[] necessaryResult = {
    // put here all necessary result for this rule
    // example: 
    // ResultName.MATRIX_BIOMASS,
    // ResultName.MATRIX_NET_VALUE_OF_LANDINGS_PER_STRATEGY_MET,
    };

    @Override
    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
     */
    @Override
    public String getDescription() throws Exception {
        return _("l'abondance de poissons captur" + " ne seront pas captur"
                + " suivant la proportion de survie.");
    }

    /**
      * des valeurs
     * 
     * @param context La simulation pour lequel on utilise cette regle
     */
    @Override
    public void init(SimulationContext context) throws Exception {
    }

    /**
     * @param context
     * @param date
     * @param param_species
     * @param metier
     * @return
     */
    ///    private boolean isCaptureDate(TimeStep step, Species species, Metier metier) {
    ///        MetierSeasonInfo info = metier.getMetierSeasonInfo(step.getMonth());
    ///        TargetSpecies target = info.getSpeciesTargetSpecies(species);

    //        boolean result;
    //        if (target != null) {
    //            result = true;
    //        } else {
    //            result = false;
    //        }

    //        return result;
    //    }

    /**
     * La condition qui doit etre vrai pour faire les actions
     * 
     * @param context La simulation pour lequel on utilise cette regle
     * @return vrai si on souhaite que les actions soit faites
     */
    @Override
    public boolean condition(SimulationContext context, TimeStep step, Metier metier)
            throws Exception {
        //log.info("Recherche si la taille Minimale s'applique");
        boolean result = true;
        if (step.before(param_beginStep)) {
            result = false;
        } else if (step.after(param_endStep)) {
            result = false;
        }
        ////else if (isCaptureDate(date, param_species, metier) != true) {
        ////result = false;
        ////}

        log.info("fin de condition TailleMin:" + result);
        return result;

        // fin
    }

    /**
     * Si la condition est vrai alors cette action est execut
          * temps de la simulation.
     * 
     * @param context La simulation pour lequel on utilise cette regle
     */
    @Override
    public void preAction(SimulationContext context, TimeStep step, Metier metier)
            throws Exception {
        // nothing
    }

    /**
     * Si la condition est vrai alors cette action est execut
          * temps de la simulation.
     * @param context La simulation pour lequel on utilise cette regle
     */
    @Override
    public void postAction(SimulationContext context, TimeStep step, Metier metier)
            throws Exception {
        //log.info("*$*$*$* TailleMin.actionApres:" + date + " metapop:"
        //        + param_species + " metier:" + metier);

        // ATTENTION        
        // les captures pour cette metapop ne sont plus du qu'au metier pour qui 
        // l'espece est secondaire: elles sont affectees aux rejets

        //pb : ne se fait pas par metier
        //il faut une matrice pour chaques pas de temps qui stocke les rejets 
        //par metier, par metapop et par classes d'age (comme pour les captures)
        //////
        log.info("deb de affecterCaptureREJETTailleMin");

        PopulationMonitor popMon = context.getPopulationMonitor();
        SiMatrix siMatrix = SiMatrix.getSiMatrix(context);
        List<Population> pops = siMatrix.getPopulations(step);
        List<Strategy> strategies = siMatrix.getStrategies(step);


        for (Population pop : pops) {
           if (pop.getSpecies().equals(param_species)) {
                MatrixND discard = popMon.getCatch(pop).copy();
				MatrixND eff = popMon.getN(pop);
                for (Strategy str : strategies) {
                	List<PopulationGroup> groups = pop.getPopulationGroup();
                    for (PopulationGroup group : groups) {
                         List<Zone> zones = pop.getPopulationZone(); 
                         for (Zone zone : zones) {
                         	double value=0;
                			discard.setValue(str,metier,group,zone,value); // initialise discard si pas de rejet (ie taille>=TailleMin et pas metierLangoustine)
							if (metier.getName().equals("metier lang simp Sud")||metier.getName().equals("metier lang simp Nord")||metier.getName().equals("metier lang simple")||metier.getName().equals("metier lang jum Nord")||metier.getName().equals("metier lang jum Sud")||metier.getName().equals("metier lang jum")) {
							  double propTrie = 1 / (1 + Math.exp(-(group.getLength() - param_Retention_L50)/ param_Retention_slope));
							  double propRejet = 1 - propTrie;
							  log.info("REJETS" + propRejet);
							  value = popMon.getCatch(pop).getValue(str, metier, group, zone) * propRejet;
							  log.info("VALUE" + value);
							  discard.setValue(str, metier, group, zone, value);
							  
							}else if (group.getLength() < param_TailleMin) { 
							  value = popMon.getCatch(pop).getValue(str, metier, group, zone);
							  log.info("VALUE" + value);
							  discard.setValue(str, metier, group, zone, value);
							}
							if (param_propSurvie >0) {
							    //ajout de la survie aux effectifs
								double valueSurvie = value*param_propSurvie;
								double effAvtRejet = eff.getValue(str, metier, group, zone);
								eff.setValue(str, metier, group, zone, effAvtRejet+valueSurvie);
							}
						}   
                    }
                }
                discard.setName(ResultName.MATRIX_DISCARDS_PER_STR_MET_PER_ZONE_POP);
                popMon.addDiscard(step, pop, discard); 
           }
        }
    }
}
