/*
 * Copyright (C) 2012 jandre
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

package rules;

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

import java.util.List;

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

import scripts.ResultName;
import scripts.SiMatrix;
import fr.ifremer.isisfish.entities.Metier;
import fr.ifremer.isisfish.entities.Strategy;
import fr.ifremer.isisfish.entities.StrategyMonthInfo;
import fr.ifremer.isisfish.entities.Population;
import fr.ifremer.isisfish.entities.PopulationGroup;
import fr.ifremer.isisfish.entities.Species;
import fr.ifremer.isisfish.rule.AbstractRule;
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.Species;

import org.nuiton.math.matrix.MatrixIterator;
import fr.ifremer.isisfish.entities.MetierSeasonInfo;
import fr.ifremer.isisfish.entities.TargetSpecies;
import fr.ifremer.isisfish.simulator.PopulationMonitor;
import fr.ifremer.isisfish.util.Doc;

/**
 * Remplace aussi Cantonnement Engin.
 * 
 * Created: 10 May 2012
 * @author Jess andre
 * @version $Revision: 204 $
 */
public class TotalClosure_withSpChoice extends AbstractRule {
    
    /** to use log facility, just put in your code: log.info("..."); */
    static private Log log = LogFactory.getLog(TotalClosure_withSpChoice.class);

    public Date param_beginDate = new Date(0);
    public Date param_endDate = new Date(119);
    public Month param_beginMonth = Month.MARCH;
    public Month param_endMonth = Month.APRIL;
    @Doc(value = "Affected species")
    public Species param_species = null;
    @Doc(value = "Affected population")
    public Population param_pop = null;


    public String[] necessaryResult = {
            ResultName.MATRIX_NO_ACTIVITY
    };

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

    @Override
    public String getDescription() throws Exception {
        return _("Total closure of the fishery");
    }
//***********************************************************************************
    /**
    * Appele au demarrage de la simulation, cette methode permet d'initialiser 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);
        Species target2 = target.getSpecies();
		//log.info(" *** target2:" + target2);
		//log.info(" *** param_species:" + param_species);

        boolean result;
        if (target2.equals(param_species)) {
            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("Search if TotalClosure rules applies");
        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;
        }

        if (date.getMonth().before(param_beginMonth)) {
            result = false;
        } else if (date.getMonth().after(param_endMonth)) {
            result = false;
        } else if (isCaptureDate(date, param_species, metier) != true) {
            result = false;
        }
        
        log.info("End search for TotalClosure application:" + result);
        return result;
    }
//***********************************************************************************
    /**
     * Si la condition est vrai alors cette action est executee avant le pas
     * de 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 {               
        
        if (isCaptureDate(date, param_species, metier)) {
        	SiMatrix siMatrix = SiMatrix.getSiMatrix(context);
        	List<Population> pops = siMatrix.getPopulations(date);
	   	//log.info("****$$$** population:" + pops);
	   	//log.info("****$$$** species:" + param_pop);
   
	   	for (Population pop : pops) {
        		if(pop.getSpecies().equals(param_species)){
        		//if (pop.equals(param_pop)) {
        		log.info("****$$$** pop:" + pop);
        		log.info("****$$$** param_pop:" + param_pop);  

        		//PopulationMonitor popMon = context.getPopulationMonitor();
        		MetierMonitor metierMon = context.getMetierMonitor();
        		MatrixND noActivity = metierMon.getOrCreateNoActivity(date,
                	ResultName.MATRIX_NO_ACTIVITY, siMatrix.getStrategies(date),
                	siMatrix.getMetiers(date));
       		metierMon.addforbiddenMetier(metier);
        		List<Strategy> strategies = siMatrix.getStrategies(date);

        			for (Strategy str : strategies) {
            			StrategyMonthInfo info = str.getStrategyMonthInfo(date.getMonth());
            			double prop = info.getProportionMetier(metier);
            			if (prop != 0) {
                			noActivity.setValue(str, metier, prop);
                			info.setProportionMetier(metier, 0);
            			}
        			}
    		}
    	   }
       }
   }
            
//***********************************************************************************
    /**
     * Si la condition est vrai alors cette action est executee apres le pas
     * de 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 {
        // nothing
    }

}
