package org.lucci.madhoc.env;

import java.util.Collection;

import org.lucci.madhoc.bining.Grid;
import org.lucci.madhoc.network.Network;
import org.lucci.madhoc.network.Station;
import org.lucci.madhoc.simulation.Configurable;
import org.lucci.madhoc.simulation.Simulation;
import org.lucci.madhoc.simulation.random.RandomNumberGenerator;
import org.lucci.up.data.Figure;
import org.lucci.up.system.Space;


/*
 * Created on Jul 29, 2004
 */

/**
 * @author luc.hogie
 */
public abstract class NetworkEnvironment implements Configurable
{
    private Grid grid;
    private RadioPropagationModel radioPropagationModel;
    private Network network;
    private int surface;

    private RandomNumberGenerator randomNumberGenerator;


    public boolean isInEnv(double x, double y)
    {
        double edge = Math.sqrt(surface);
        return 0 < x && x < edge && 0 < y && y < edge; 
    }
    
    public RandomNumberGenerator getRandomNumberGenerator()
    {
        return randomNumberGenerator;
    }

    public void configure()
        throws Throwable
    {
        this.randomNumberGenerator = new RandomNumberGenerator();
//        this.randomNumberGenerator.getRandom().setSeed(564);

        Simulation simulation = getNetwork().getSimulation();
        this.surface = simulation.getConfiguration().getInteger("simulation_area_surface");
        this.grid = new Grid(surface);
    }
    
    
    /**
     * @return Returns the mobilityModel.
     */
    public abstract Class getDefaultMobilityModel();


    /**
     * @return Returns the radioPropagationModel.
     */
    public RadioPropagationModel getRadioPropagationModel()
    {
        return radioPropagationModel;
    }

    /**
     * @param radioPropagationModel The radioPropagationModel to set.
     */
    public void setRadioPropagationModel(RadioPropagationModel radioPropagationModel)
    {
        if (radioPropagationModel == null)
            throw new IllegalArgumentException();
    
        this.radioPropagationModel = radioPropagationModel;
        this.radioPropagationModel.setNetworkEnvironment(this);
    }
    
    public void initializeNodesLocation(Collection<Station> stations, int maxIteration, double timeStep)
    {
        for (long iteration = 0; iteration < maxIteration; ++iteration)
          { 
              for (Station station : stations)
              {
                  station.getMobilityModel().moveStation(timeStep, timeStep * iteration);
              }
          }

        //      List distances = new Vector();
//      int step = 10000;
//      
//      for (long iteration = 0;; ++iteration)
//      { 
//          for (Station station : stations)
//          {
//              station.getMobilityModel().moveStation(step, step * iteration);
//          }
//
////            getNetwork().removeInvalidConnections();
////            getNetwork().findNewConnections();
//          distances.add(new Double(Geometry.getAverageDistanceBetweenStationsInRange(getNetwork())));
//
//          if (distances.size() >= 10)
//          {
//              double deviation = Utilities.getStandardDeviation(distances.subList(distances.size() - 10, distances.size()));
//
//              if ( deviation < 1)
//                      break;
//          }
//      }
    }

    public Grid getGrid()
    {
        return grid;
    }

    public Network getNetwork()
    {
        return network;
    }
    public void setNetwork(Network network)
    {
        this.network = network;
    }
    
    public abstract Figure createFigure(Space space);


    public int getSurface()
    {
        return surface;
    }
}