package brn.sim.scenario.txdor;

import jist.swans.Constants;
import jist.swans.misc.Util;
import brn.distsim.ormapper.util.DbBinaryLoader;
import brn.sim.AbstractParams;
import brn.sim.BasicDriver;
import brn.sim.builder.MetricBuilder;
import brn.sim.builder.RouteBuilder;
import brn.sim.builder.TransBuilder;
import brn.sim.builder.FlowBuilder.TcpParams;
import brn.sim.data.FlowStats;
import brn.sim.handler.LinkQualityHandler;

/**
 * @deprecated
 * @author kurth
 */
public class TxDOrSim extends BasicDriver {

  /**
   * @deprecated
   * @author kurth
   */
  public static class FlowResult {
    public int flowId;
    public FlowStats flowStats;
    public DelayStats delayStats;
    public ReorderDensityStats rdStats;
  }

  /**
   * @deprecated
   * @author kurth
   */
  public static class DelayStats {
    public int simulationId;
    public double min;
    public double percentile05;
    public double mean;
    public double percentile95;
    public double max;
    public double stddev;
    public DelayStats(int simulationId, double min, double percentile05,
        double mean, double percentile95, double max, double stddev) {
      super();
      this.simulationId = simulationId;
      if (!Double.isNaN(min))
        this.min = min;
      if (!Double.isNaN(percentile05))
        this.percentile05 = percentile05;
      if (!Double.isNaN(mean))
        this.mean = mean;
      if (!Double.isNaN(percentile95))
        this.percentile95 = percentile95;
      if (!Double.isNaN(max))
        this.max = max;
      if (!Double.isNaN(stddev))
        this.stddev = stddev;
    }
  }

  /**
   * @deprecated
   * @author kurth
   */
  public static class ReorderDensityStats {
    public int simulationId;
    public double min;
    public double percentile05;
    public double mean;
    public double percentile95;
    public double max;
    public double stddev;
    public ReorderDensityStats(int simulationId, double min, double percentile05,
        double mean, double percentile95, double max, double stddev) {
      super();
      this.simulationId = simulationId;
      if (!Double.isNaN(min))
        this.min = min;
      if (!Double.isNaN(percentile05))
        this.percentile05 = percentile05;
      if (!Double.isNaN(mean))
        this.mean = mean;
      if (!Double.isNaN(percentile95))
        this.percentile95 = percentile95;
      if (!Double.isNaN(max))
        this.max = max;
      if (!Double.isNaN(stddev))
        this.stddev = stddev;
    }
  }

  // TODO remove
  public void evalSimulationResults(String dbUrl, String dbUser, String dbPasswd,
      String driver, String version,
      String dbResUrl, String dbResUser, String dbResPasswd) throws Throwable {
    MultiFlow flow = new MultiFlow();
    flow.evalSimulationResults(dbUrl, dbUser, dbPasswd, driver, version,
        dbResUrl, dbResUser, dbResPasswd);
  }

  protected Object load(DbBinaryLoader loader, int simulationId, String configPath,
      boolean error) throws Exception  {
    Object ret = loader.load(simulationId, configPath);
    if (null == ret && error) {
      throw new Error("Object with path " + configPath + " not found for id " + simulationId);
    }
    return ret;
  }

  protected Object load(DbBinaryLoader loader, int simulationId, String configPath)
  throws Exception  {
    Object ret = loader.load(simulationId, configPath);
    if (null == ret) {
      throw new Error("Object with path " + configPath + " not found for id " + simulationId);
    }
    return ret;
  }

  /*
   * (non-Javadoc)
   * @see brn.sim.AbstractDriver#installHandlers(brn.sim.AbstractParams)
   */
  protected void installHandlers(AbstractParams opts) throws Exception {
    super.installHandlers(options);

    LinkQualityHandler linkQualityHandler = (LinkQualityHandler)
      this.dataManager.getContributor(LinkQualityHandler.ID);

    if (null != linkQualityHandler && null != opts.node.route) {
      MetricBuilder.EtxParams params = (MetricBuilder.EtxParams)
        ((RouteBuilder.BrnDsrParams)opts.node.route).metric;
      linkQualityHandler.setSampleLen(/*to sec*/ params.tau / 1000);
    }
  }

//  /*
//   * (non-Javadoc)
//   * @see brn.sim.AbstractDriver#setupApplication(brn.sim.AbstractParams, int, jist.swans.Node)
//   */
//  protected void setupApplication(AbstractParams opts, int nodeId, Node node) throws BuilderException {
//    super.setupApplication(opts, nodeId, node);
//    TxDOrParams params = (TxDOrParams)opts;
//
//    //    transport
//    if (null != params.transParams) {
//      Builder builder = builderProvider.getBuilder(params.transParams);
//      AbstractTrans trans = (AbstractTrans) builder.build(params.transParams, node);
//      builderProvider.addHookUp(builder, params.transParams, node, trans);
//      node.addTransport(trans);
//    }
//
//    // app
//    if (null != params.trafficParams) {
//      Builder builder = builderProvider.getBuilder(params.trafficParams);
//      Object ret = builder.build(params.trafficParams, node);
//      builderProvider.addHookUp(builder, params.trafficParams, node, ret);
//    }
//  }

    protected void runFile(String fileName) {
      try {
      AbstractParams params = (AbstractParams) Util.readObject(fileName);
        params.db = true;
        params.dbRes = "jdbc:mysql://localhost:3306/simulation";
        params.dbDef = "jdbc:mysql://localhost:3306/simulation";
        run(params);
      } catch (Throwable e) {
        e.printStackTrace();
        System.exit(1);
      }
  }

  /*
   * (non-Javadoc)
   * @see brn.sim.AbstractDriver#runLocal()
   */
  protected void runLocal() {
    runLocalEtt();
    //runLocalTcp();
  }

  protected void runLocalTcp() {
    TxDOrParams params = MultiFlowTcp.getParams(10, 2, 8., 3,
        Constants.BANDWIDTH_6Mbps, 1);

    TransBuilder.TcpParams tcp = (TransBuilder.TcpParams)params.transParams;
    TcpParams tcpParams = (TcpParams) params.trafficParams.flowParams;
    tcpParams.tcpBytes = tcp.mss * 10;

    params = params.setParamsTest();
    params.dumpNet = true;
//  params.handlerRadioEx = true;
//  params.handlerRadioTimeBar = true;

  try {
    run(params);
  } catch (Throwable e) {
    e.printStackTrace();
    System.exit(1);
  }
  }

  protected void runMultiFlowCBR() {
    TxDOrParams params = MultiFlowCBR.getParams(100, 2, 8., 3,
        Constants.BANDWIDTH_6Mbps, 2, 80*2, 100/2, 100, true, false);
    params = params.setParamsTest();
//    params.handlerRadioEx = true;
//    params.handlerRadioTimeBar = true;

    try {
      run(params);
    } catch (Throwable e) {
      e.printStackTrace();
      System.exit(1);
    }
  }

  protected void runMultiFlow() {
    TxDOrParams params = MultiFlow.getParams(200, 4, 8., 3, Constants.BANDWIDTH_6Mbps, 1);
    params = params.setParamsTest();

    try {
      run(params);
    } catch (Throwable e) {
      e.printStackTrace();
      System.exit(1);
    }
  }

  protected void runLocalMacPromisc() {
  TxDOrParams params =
      TxDOrParams.defaultParams(new TxDOrParams());
//    TxDOrParams.unicastParams(new TxDOrParams());

  params.seed = 2;
  params.nodes = 50;

//  params.setMetricAndBitRate(true, 500,
    params.setMetricAndBitRate(false, 500,
//  params.setMetricAndBitRate(false, 50000,
      Constants.BANDWIDTH_6Mbps, Constants.BANDWIDTH_6Mbps);


//    FieldBuilder.FieldParams field = (FieldBuilder.FieldParams)params.field;
//    field.fieldX = 20000;
//    field.fieldY = 20000;
//    field.spatial_mode = Constants.SPATIAL_HIER;
//    field.propDelay = Constants.PROPAGATION_DELAY_FIXED;
//    field.propDelayFixed = Constants.PROPAGATION;
//    field.propDelay = Constants.PROPAGATION_DELAY_DIST_NORMAL;
//    field.propDelayStdDev = 250.;
//  field.fading = Constants.FADING_RICIAN;
//  field.fadingRicianFactor = 4.;
//    params.field = field;

//    DistShadowingParams pathLoss = (DistShadowingParams) field.pathloss;
//    pathLoss.exponent = 2.7;
//    pathLoss.stdDeviation = 12.;
//    pathLoss.coherenceTime = 0 * Constants.SECOND;

//    RadioBuilder.NoiseParams radio = (RadioBuilder.NoiseParams) params.node.radio;
//    radio.fieldX = field.fieldX;
//    radio.fieldY = field.fieldY;
//    radio.min_connectivity_betweenNodes = 0;

//  MacBuilder.M802_11TxDivParams mac = (MacBuilder.M802_11TxDivParams) params.node.mac;
//  mac.promiscStorePackets = true;

  //  MacBuilder.M802_11Params mac = (MacBuilder.M802_11Params) params.node.mac;
  //    MacBuilder.M802_11Params mac = new MacBuilder.M802_11Params();
  //  mac.thresholdRts = 500;
  //    params.node.mac = mac;

//    RouteBuilder.TxDORParams route = (RouteBuilder.TxDORParams) params.node.route;
  //  RouteBuilder.BrnDsrParams route = (RouteBuilder.BrnDsrParams) params.node.route;
  //  route.candidateSetSize = 3;
//    route.candidateSelection = brn.swans.Constants.TXDOR_CSSEL_CONSERVATIVE;
//    route.noCandSets = 3;
//    route.candidateSelection = brn.swans.Constants.TXDOR_CSSEL_ETT;
//    route.candidateSelection = brn.swans.Constants.TXDOR_CSSEL_ROBCONRAT;
//    route.candidateSelection = brn.swans.Constants.TXDOR_CSSEL_LESSCONS;

//    ((AppBuilder.UdpNotifyParams)params.trafficParams.flowParams).start = 80000;
//    ((AppBuilder.UdpNotifyParams)params.trafficParams.flowParams).end = 82000;
//    ((AppBuilder.UdpCaParams)params.trafficParams.flowParams).maxOutstandingPackets = 180;

    params = params.setParamsBatch();
    params.handlerRadioEx = false;
//    params.handlerLinkQuality = true;
//    params.handlerRadioTimeBar = true;
    params.db = true;
    params.dbRes = "jdbc:mysql://localhost:3306/simulation";
    params.dbDef = "jdbc:mysql://localhost:3306/simulation";
//    params.file = true;
//    params.directory = "/tmp/test-2";

    try {
      run(params);
    } catch (Throwable e) {
      e.printStackTrace();
      System.exit(1);
    }
  }

  protected void runLocalEtt() {
    TxDOrParams params = TxDOrParams.defaultParams(new TxDOrParams());
//    TxDOrParams params = TxDOrParams.unicastParams(new TxDOrParams());
    params = TxDOrParams.radioBerParams(params);

    int dataRate = Constants.BANDWIDTH_6Mbps;

    params.seed = 2;
//    params.nodes = 50;
    params.nodes = 25;

    params.setMetricAndBitRate(false, 500, dataRate, Constants.BANDWIDTH_6Mbps);

//      FieldBuilder.FieldParams field = (FieldBuilder.FieldParams) params.field;
//      field.exponent = 2.7;
//      field.stdDeviation = 4.;
//
//      RadioBuilder.NoiseParams radio = (RadioBuilder.NoiseParams) params.node.radio;
//      radio.placement = Constants.PLACEMENT_GRID;
//      radio.placementOpts = "4x3";

//    MacBuilder.M802_11TxDivParams mac = (MacBuilder.M802_11TxDivParams) params.node.mac;
//    MacBuilder.M802_11Params mac = (MacBuilder.M802_11Params) params.node.mac;
//      MacBuilder.M802_11Params mac = new MacBuilder.M802_11Params();
//    mac.thresholdRts = 500;
//      params.node.mac = mac;

//    RouteBuilder.TxDORParams route = (RouteBuilder.TxDORParams) params.node.route;
//    RouteBuilder.BrnDsrParams route = (RouteBuilder.BrnDsrParams) params.node.route;
//    route.candidateSetSize = 3;
//    route.candidateSelection = brn.swans.Constants.TXDOR_CSSEL_CONSERVATIVE;
//    route.candidateSelection = brn.swans.Constants.TXDOR_CSSEL_ROBCONRAT;


    params = params.setParamsBatch();
    params.handlerRadio = true; // too big
    params.handlerRadioEx = true; // too big, to slow
    params.handlerRate = true;
    params.handlerLinkTable = true;
//    params.handlerLinkQuality = true;
    params.handlerRadioTimeBar = true;
    params.db = false;
    params.dbRes = "jdbc:mysql://localhost:3306/simulation";
    params.dbDef = "jdbc:mysql://localhost:3306/simulation";

    try {
      run(params);
    } catch (Throwable e) {
      e.printStackTrace();
      System.exit(1);
    }
  }

  public static void main(String[] args) throws Throwable {
    TxDOrSim test = new TxDOrSim();
    test.run(args);
  }

}
