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.Date;
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.types.Date;
import fr.ifremer.isisfish.util.Doc;

/**
 * Cette methode remplace aussi TailleMinSurvieRejet si propSurvie est > 0
 * 
 * Created: 30 novembre 2006
 *
 * @author anonymous <anonymous@labs.libre-entreprise.org>
 * @version $Revision: 1.1 $
 *
 * Last update: $Date: 2007-01-24 18:25:34 $
 * by : $Camille de la Vega $
 */
public class Ogive_de_Trie extends AbstractRule {

    /** to use log facility, just put in your code: log.info("..."); */
    static private Log log = LogFactory.getLog(Ogive_de_Trie.class);

    @Doc(value = "Begin date")
    public Date param_beginDate = new Date(0);

    @Doc(value = "End date")
    public Date param_endDate = new Date(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 = "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(Date date, Species species, Metier metier) {
    ///        MetierSeasonInfo info = metier.getMetierSeasonInfo(date.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, Date date, Metier metier)
            throws Exception {
        //log.info("Recherche si la taille Minimale s'applique");
        boolean result = true;
        if (date.before(param_beginDate)) {
            result = false;
        } else if (date.after(param_endDate)) {
            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, Date date, 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, Date date, 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(date);
        List<Strategy> strategies = siMatrix.getStrategies(date);

        for (Strategy str : strategies) {
            for (Population pop : pops) {
                if (pop.getSpecies().equals(param_species)) {
                    ///if (popMon.getDiscard(date, pop) == null) {
                    MatrixND discard = popMon.getCatch(pop).copy();
                    /// MatrixND eff = popMon.getN(pop);
                    List<PopulationGroup> groups = pop.getPopulationGroup();
                    for (PopulationGroup group : groups) {
                      List<Zone> zones = pop.getPopulationZone(); 
                      for (Zone zone : zones) {	
                         if (metier.getName().equals("metier lang simp Sud")) {
                            double trie = 1 / (1 + Math.exp(-(group.getLength() - param_Retention_L50)/ param_Retention_slope));
                            double rejet = 1 - trie;
                            log.info("REJETS" + rejet);
                            //List<Zone> zones = pop.getPopulationZone(); 
                            //for (Zone zone : zones) {	
					   double value = popMon.getCatch(pop).getValue(str, metier, group, zone) * rejet;
					   log.info("VALUE" + value);
                            discard.setValue(str, metier, group, zone, value);}
                         else{
                            double sanstrie=0;
                            discard.setValue(str, metier, group, zone, sanstrie);}
                        }
                    }
                    discard.setName(ResultName.MATRIX_DISCARDS_PER_STR_MET_PER_ZONE_POP);;
                    popMon.addDiscard(date, pop, discard);
                }
            }
        }
    }
}
