package rules;

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

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.math.matrix.MatrixFactory;
import org.nuiton.math.matrix.MatrixND;

import scripts.ResultName;
import fr.ifremer.isisfish.IsisFishDAOHelper;
import fr.ifremer.isisfish.entities.Metier;
import fr.ifremer.isisfish.entities.MetierDAO;
import fr.ifremer.isisfish.entities.Population;
import fr.ifremer.isisfish.entities.PopulationDAO;
import fr.ifremer.isisfish.entities.PopulationGroup;
import fr.ifremer.isisfish.entities.Zone;
import fr.ifremer.isisfish.entities.ZoneDAO;
import fr.ifremer.isisfish.rule.AbstractRule;
import fr.ifremer.isisfish.simulator.SimulationContext;
import fr.ifremer.isisfish.types.TimeStep;

/**
 * Rule to set temperature variable on zone.
 * 
 * @author chatellier
 * @version $Revision$
 * 
 * Last update : $Date$
 * By : $Author$
 */
public class ZoneBenthos extends AbstractRule {

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

    protected List<String> zonenames;
	protected List<String> metiernames;

    protected TimeStep ruleStep;

	// Ici on tente de lier la mortalite du benthos a une quantite de poisson (plie par exemple) capturee.
	// On fait le test avec cette matrice car elle est definie par zone metier.
	// Il faut creer un export qui contient un temps de peche par zone metier, car la mortalite du benthos 
	// est en general liee a la duree de l'activite qui l'impacte.
    public String[] necessaryResult = {
            ResultName.MATRIX_CATCH_PER_STRATEGY_MET_PER_ZONE_MET,
            n_("matrixGranularite")
    };

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

    /*
     * @see fr.ifremer.isisfish.rule.Rule#init(fr.ifremer.isisfish.simulator.SimulationContext)
     */
    @Override
    public void init(SimulationContext context) throws Exception {

        List<Integer> steps = new ArrayList<Integer>();
        for (int s = 0; s < 120; ++s) {
            steps.add(s);
        }

        zonenames = new ArrayList<String>();
        zonenames.add("28E8");
        zonenames.add("28E9");
        zonenames.add("28F0");
        zonenames.add("29E9");
		zonenames.add("29F0");
		zonenames.add("29F1");
		zonenames.add("30F0");
		zonenames.add("30F1");
		zonenames.add("27E9");
        zonenames.add("VIId_DRBleft");
        //zonenames.add("28E9_Granulats_Havrais_PER");
        //zonenames.add("28E9_Granulats_GIE_GMO");
        //zonenames.add("29F0_Granulats_GIE_Saint_Nicolas");
        //zonenames.add("29F0_Granulats_Hastings");
		//zonenames.add("30F0_Granulats_Hastings");
		//zonenames.add("VIId_DRB_left_Granulats_South_Coast");

		metiernames = new ArrayList<String>();
		metiernames.add("GTR_27E9");
		metiernames.add("GTR_28E8");
		metiernames.add("GTR_28E9");
		metiernames.add("GTR_28F0");
		metiernames.add("GTR_29F0");
		metiernames.add("GTR_29F1");
		metiernames.add("GTR_30F1");
		metiernames.add("GTR_VIId");

        ruleStep = new TimeStep(0);
    }

    /*
     * @see fr.ifremer.isisfish.rule.Rule#condition(fr.ifremer.isisfish.simulator.SimulationContext, fr.ifremer.isisfish.types.TimeStep, fr.ifremer.isisfish.entities.Metier)
     */
    @Override
    public boolean condition(SimulationContext context, TimeStep step,
            Metier metier) throws Exception {
        if (ruleStep.getStep() < 120) {
            return true;
        } else {
            return false;
        }
    }

    /*
     * @see fr.ifremer.isisfish.rule.Rule#getDescription()
     */
    @Override
    public String getDescription() throws Exception {
        return _("Modify benthos abundance for zones");
    }

    /*
     * @see fr.ifremer.isisfish.rule.Rule#preAction(fr.ifremer.isisfish.simulator.SimulationContext, fr.ifremer.isisfish.types.TimeStep, fr.ifremer.isisfish.entities.Metier)
     */
    @Override
    public void preAction(SimulationContext context, TimeStep step,
            Metier metier) throws Exception {

    }

    /*
     * @see fr.ifremer.isisfish.rule.Rule#postAction(fr.ifremer.isisfish.simulator.SimulationContext, fr.ifremer.isisfish.types.TimeStep, fr.ifremer.isisfish.entities.Metier)
     */
    @Override
    public void postAction(SimulationContext context, TimeStep step,
            Metier metier) throws Exception {

		// Sur une unique population pour le moment	
        PopulationDAO dao = IsisFishDAOHelper.getPopulationDAO(context.getDB());
        Population Plaice_Seine_Veys = dao.findByName("Plaice_Seine_Veys");

        if (step.equals(ruleStep)) {

            // handle granularite
            List<Zone> zones = new ArrayList<Zone>();
            ZoneDAO zoneDAO = IsisFishDAOHelper.getZoneDAO(context.getDB());
            for (String zonename : zonenames) {
                Zone zone = zoneDAO.findByName(zonename);
                zones.add(zone);

                // timestep, group, zone
                MatrixND C = context.getResultManager().getMatrix(step, Plaice_Seine_Veys, ResultName.MATRIX_CATCH_PER_STRATEGY_MET_PER_ZONE_MET);
				    /**
				 * Dimension 1(0) : Strategy
				 * Dimension 2(1) : Metier
				 * Dimension 3(2) : Group
				 * Dimension 4(3) : Zone
				 */

				 // On n'est interesses que par certains metiers (DRB, qui sont pratiques uniquement par certaines strategies).
				 // Si on selectionne en premier sur les metiers on ne devrait pas avoir besoin de selectionner sur les
				 // strategies car si un metier n'appartient pas a une strategies les captures pour l'intersection des 
				 // deux devraient etre nulles.
				 
				 MatrixND Ctot = C.sumOverDim(0); // Somme sur toutes les strategies
				 Ctot = Ctot.sumOverDim(2); // Somme sur tous les groupes
				 Ctot = Ctot.reduce(); // remove groups dim
				 	/**
				 * Dimension 1(0) : Metier
				 * Dimension 2(1) : Zone
				 */
				 							
				List<Metier> metiers = new ArrayList<Metier>();
				MetierDAO metierDAO = IsisFishDAOHelper.getMetierDAO(context.getDB());
				for (String metiername : metiernames) {
					Metier met = metierDAO.findByName(metiername);
					metiers.add(met);
				 		 
					double CtotMet_PerZone = Ctot.getValue(met, zone);
					
					double Carnivore = context.get(zone).getAsDouble("Carnivore");
					Carnivore -= Carnivore / (CtotMet_PerZone * 1000);
					context.get(zone).set("Carnivore", Carnivore);
				}
            }

            // save Carnivore result
            MatrixND CarnivoreMatrix = MatrixFactory.getInstance().create(n_("matrixCarnivore"),
                    new List[] { zones }, new String[] { n_("Zones")});
            for (Zone zone : zones) {
                double Carnivore = context.get(zone).getAsDouble("Carnivore");
                CarnivoreMatrix.setValue(zone, Carnivore);
            }
            context.getResultManager().addResult(step, Plaice_Seine_Veys, CarnivoreMatrix);
            
            // to run preAction/postAction only once by step
            ruleStep = ruleStep.next();
        }
    }
}
