/*
 * Copyright (C) 2014 slehuta
 *
 * 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 3 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, see
 * <http://www.gnu.org/licenses/gpl-3.0.html>.
 */
 
package simulationplans;

import fr.ifremer.isisfish.*;
import fr.ifremer.isisfish.datastore.ResultStorage;
import fr.ifremer.isisfish.datastore.RuleStorage;
import fr.ifremer.isisfish.datastore.SimulationStorage;
import fr.ifremer.isisfish.entities.*;
import fr.ifremer.isisfish.rule.Rule;
import fr.ifremer.isisfish.rule.RuleHelper;
import fr.ifremer.isisfish.simulator.SimulationContext;
import fr.ifremer.isisfish.simulator.SimulationParameter;
import fr.ifremer.isisfish.simulator.SimulationPlan;
import fr.ifremer.isisfish.simulator.SimulationPlanContext;
import fr.ifremer.isisfish.types.TimeStep;
import fr.ifremer.isisfish.util.Doc;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.Writer;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.math.matrix.*;
import org.nuiton.topia.*;
import org.nuiton.util.*;
import scripts.ResultName;

/**
 * PlanSocioec.java
 *
 * Created: 9 septembre 2014
 *
 * @author slehuta <user.name@vcs.hostName>
 * @version $Revision: 1545 $
 * Last update: $Date: 9 septembre 2014 $
 * by : $Author: slehuta $
 */
public class PlanSocioec implements SimulationPlan {

    /** to use log facility, just put in your code: log.info("..."); */
    private static Log log = LogFactory.getLog(PlanSocioec.class);
    
    static private final String MATRIX = "matrix";
    private MatrixND matrix = null;
	static private final String EPSsol = "epsSol";
	static private final String EPSple = "epsPle";
	static private final String EPSmur = "epsMur";
    static private final String MIGsol = "migSol";
	static private final String MIGple = "migPle";
	static private final String MIGmur = "migMur";
	
	static private final String FUELprice = "fuel";

	// mesures de gestion
    static private final String MLSsol = "MLSsole";
    static private final String MLSple = "MLSplaice";
    static private final String HCR = "HCR"; 
    static private final String TAC = "TAC"; 
    static private final String GRAVITY = "Gravity";
        
		
    int param_parameterNumber = 12;
    public int param_first = 0;
    public int param_simulationNumber = 3636;
    public String param_directory = "InputMixChannel/PlanSocioec/";
    
    protected 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 le plan.
     * @return L''aide ou la description du plan
     */
    @Override
    public String getDescription() throws Exception {
        // TODO change description
        return "TODO PlanSocioec description plan";
    }

    /**
     * Called once before {@code beforeSimulation} call.
     * 
     * @param context plan context
     */
    @Override
    public void init(SimulationPlanContext context) throws Exception {
        matrix = MatrixFactory.getInstance().create(new int[]{param_simulationNumber, param_parameterNumber});
        matrix.importCSV(new FileReader(new File(param_directory, MATRIX + ".txt")), new int[]{0,0});
        matrix.setSemantic(1, Arrays.asList(new String[]{HCR,MLSsol,MLSple,TAC,GRAVITY,EPSsol,EPSple,EPSmur,MIGsol,MIGple,MIGmur,FUELprice}));
		System.out.println(matrix);	
        context.getParam().addExtraRules("HCR_transition_MSY","HCR_MixChannel_length","TailleMin_LandingsObligation","TailleMin","TACrejet","TAC_LO_forbiddenMet","GravityModelMixChannel");

    }
    /**
     * @param name le nom de l'element a recuperer
     * @param simulation le numero de la simulation
     * @return
     */
    private double getDouble(String name,String colname, int simulation) throws Exception {
        File dir = new File(param_directory);
        Properties prop = new Properties();
        prop.load(new BufferedReader(new FileReader(new File(dir, name + ".txt"))));
        int ligne = simulation + param_first;
		int mod = (int)matrix.getValue(ligne, colname);
		//System.out.println("nom "+name+"mod :"+mod);
        double result = Double.parseDouble(prop.getProperty(""+mod));
        return result;
    }

    /**
     * @param name le nom de l'element a recuperer
     * @param simulation le numero de la simulation
     * @return
     */    
  private double [] getList(String name,String colname ,int simulation) throws Exception {
        File dir = new File(param_directory);
        Properties prop = new Properties();
        prop.load(new BufferedReader(new FileReader(new File(dir, name + ".txt"))));
        System.out.println("getList simulation ="+simulation+" colname :"+colname +"first ="+param_first);
		int ligne = simulation + param_first;
		
        int mod = (int)matrix.getValue(ligne, colname);
        double [] result = StringUtil.toArrayDouble(prop.getProperty(""+mod).split(";"));
        return result;
    }

    /**
     * @param name le nom de l'element a recuperer
     * @param simulation le numero de la simulation
     * @return
     */
    private String getString(String name, String colname ,int simulation) throws Exception {
        File dir = new File(param_directory);
        Properties prop = new Properties();
        prop.load(new BufferedReader(new FileReader(new File(dir, name + ".txt"))));
		int ligne = simulation + param_first;
        int mod = (int)matrix.getValue(ligne , colname);
        String result = prop.getProperty(""+mod);
        return result;
    }
	
    /**
     * @param name le nom de l'element a recuperer
     * @param simulation le numero de la simulation
     * @return
     */  
    private Rule getRule(TopiaContext tc, String name, int simulation) throws Exception {
        File dir = new File(param_directory);
        Properties prop = new Properties();
        prop.load(new BufferedReader(new FileReader(new File(dir, name+".txt"))));
		int ligne = simulation + param_first;
        System.out.println("Val 0 "+matrix.getValue(0,"HCR"));
        int mod = (int)matrix.getValue(ligne , name);
        String ruleName = prop.getProperty(""+mod);
	System.out.println("ruleName : "+ ruleName);
	System.out.println("properties : "+ prop.getProperty(""+mod,"beginDate"));
	
        RuleStorage ruleStorage = RuleStorage.getRule(ruleName);
        Rule rule = ruleStorage.getNewInstance();
        RuleHelper.populateRule(mod, tc, rule, prop); 
        return rule;
    }

    /**
     * Call before each simulation.
     * 
     * @param context plan context
     * @param nextSimulation storage used for next simulation
     * @return true if we must do next simulation, false to stop plan
     * @throws Exception
     */
    @Override
    public boolean beforeSimulation(SimulationPlanContext context,
            SimulationStorage nextSimulation) throws Exception {
     int simNum = nextSimulation.getParameter().getSimulationPlanNumber();
        System.out.println("simNum ="+simNum);
        //int simNum = context.getNumber();
        if (simNum < param_simulationNumber) {
            if(simNum>35){ // premieres simus sans alea
                double[] epssol	= getList (EPSsol,EPSsol, simNum);
                double[] epsple	= getList (EPSple,EPSple, simNum);
                double[] epsmur	= getList (EPSmur,EPSmur, simNum);
                double[] migsol	= getList (MIGsol,MIGsol, simNum);
                double[] migple	= getList (MIGple,MIGple, simNum);
                double[] migmur	= getList (MIGmur,MIGmur, simNum);
                double[] fuelprice = getList(FUELprice,FUELprice,simNum);

                /*context.set("epsSRSole",epssol);
                context.set("epsSRPlaice",epsple);
                context.set("epsSRRedMullet",epsmur);
                context.set("migSole",migsol);
                context.set("migPlaice",migple);
                context.set("migRedMullet",migmur);

                context.set("fuelprice",fuelprice);

                nextSimulation.getParameter().getTagValue().put("coefvpuepel1",String.valueOf(coefvpuepel1));
                nextSimulation.getParameter().getTagValue().put("coefvpuepel2",String.valueOf(coefvpuepel2));
                nextSimulation.getParameter().getTagValue().put("coefvpuebol1",String.valueOf(coefvpuebol1));
                nextSimulation.getParameter().getTagValue().put("coefvpuebol2",String.valueOf(coefvpuebol2));
                nextSimulation.getParameter().getTagValue().put("coefeffpel1",String.valueOf(coefeffpel1));
                nextSimulation.getParameter().getTagValue().put("coefeffpel2",String.valueOf(coefeffpel2));
                nextSimulation.getParameter().getTagValue().put("coefeffbol1",String.valueOf(coefeffbol1));
                nextSimulation.getParameter().getTagValue().put("coefeffbol2",String.valueOf(coefeffbol2));*/
            
            }
            //////////////////////////////////////////////////////////////////////////////////////////

		// Modif rules
			Rule hcr = getRule(nextSimulation.getStorage(), HCR, simNum);
            Rule mlssol	= getRule(nextSimulation.getStorage(), MLSsol, simNum);
            Rule mlsple = getRule(nextSimulation.getStorage(), MLSple, simNum);
            Rule tac= getRule(nextSimulation.getStorage(), TAC, simNum);
            Rule gravity = getRule(nextSimulation.getStorage(), GRAVITY, simNum);
           
            List<Rule> paramRules = nextSimulation.getParameter().getRules();
            // on ajoute les regles
            paramRules.add(hcr);
            paramRules.add(mlssol);
            paramRules.add(mlsple);
            paramRules.add(tac);
            paramRules.add(gravity);
            

            return true;
        } else {
            return false;
        }       

    }

    /**
     * Call after each simulation.
     * 
     * @param context plan context
     * @param lastSimulation storage used for simulation
     * @return true if we must do next simulation, false to stop plan
     * @throws Exception
     */
    @Override
    public boolean afterSimulation(SimulationPlanContext context,
            SimulationStorage lastSimulation) throws Exception {
        
        return true;
    }
}
