package brn.sim;

import java.io.IOException;
import java.io.Serializable;
import java.util.Random;

import jist.runtime.JistAPI;
import jist.swans.Constants;
import jist.swans.misc.Util;
import brn.sim.builder.FieldBuilder;
import brn.sim.builder.MacBuilder;
import brn.sim.builder.MetricBuilder;
import brn.sim.builder.NetBuilder;
import brn.sim.builder.PathLossBuilder;
import brn.sim.builder.RadioBuilder;
import brn.sim.builder.RateBuilder;
import brn.sim.builder.RouteBuilder;

public class ScriptParams2 extends BasicParams {

  private NodeConfig[] nodeConfigs;
  Random rnd;


  public static class NodeConfig implements Serializable, JistAPI.DoNotRewrite {
    private int srcNodeNumber;
    private int flowNumber;
    private int packetSize;
    private long startTime;
    private long endTime;
    private int destNodeNumber;
    private int sourcePort;
    private int destPort;
    private int txRate;
    private int txRate2;
    public NodeConfig() {}
    
    public void init(int sourceNodeNumber, int destNodeNumber, int flowNumber,
        int packetSize, long startTime, long endTime, int sourcePort,
        int destPort, int txRate, int txRate2) {
      this.srcNodeNumber = sourceNodeNumber;
      this.flowNumber = flowNumber;
      this.packetSize = packetSize;
      this.startTime = startTime;
      this.endTime = endTime;
      this.destNodeNumber = destNodeNumber;
      this.sourcePort = sourcePort;
      this.destPort = destPort;
      this.txRate = txRate;
      this.txRate2 = txRate2;
    }
    
    public NodeConfig(int sourceNodeNumber, int destNodeNumber, int flowNumber,
        int packetSize, long startTime, long endTime, int sourcePort,
        int destPort, int txRate, int txRate2) {
      this.srcNodeNumber = sourceNodeNumber;
      this.flowNumber = flowNumber;
      this.packetSize = packetSize;
      this.startTime = startTime;
      this.endTime = endTime;
      this.destNodeNumber = destNodeNumber;
      this.sourcePort = sourcePort;
      this.destPort = destPort;
      this.txRate = txRate;
      this.txRate2 = txRate2;
    }

    /**
     * @return the destNodeNumber
     */
    public int getDestNodeNumber() {
      return destNodeNumber;
    }

    /**
     * @return the endTime
     */
    public long getEndTime() {
      return endTime;
    }

    /**
     * @return the flowNumber
     */
    public int getFlowNumber() {
      return flowNumber;
    }

    /**
     * @return the nodeNumber
     */
    public int getNodeNumber() {
      return srcNodeNumber;
    }

    /**
     * @return the packetSize
     */
    public int getPacketSize() {
      return packetSize;
    }

    /**
     * @return the startTime
     */
    public long getStartTime() {
      return startTime;
    }

    /**
     * @return the destPort
     */
    public int getDestPort() {
      return destPort;
    }

    /**
     * @return the sourcePort
     */
    public int getSourcePort() {
      return sourcePort;
    }

    /**
     * @return the txRate
     */
    public int getTxRate() {
      return txRate;
    }
    
    /**
     * @return the txRate2
     */
    public int getTxRate2() {
      return txRate2;
    }

    /**
     * @param nodeNumber the nodeNumber to set
     */
    public void setNodeNumber(int nodeNumber) {
      this.srcNodeNumber = nodeNumber;
    }

    /**
     * @param flowNumber the flowNumber to set
     */
    public void setFlowNumber(int flowNumber) {
      this.flowNumber = flowNumber;
    }

    /**
     * @param packetSize the packetSize to set
     */
    public void setPacketSize(int packetSize) {
      this.packetSize = packetSize;
    }

    /**
     * @param startTime the startTime to set
     */
    public void setStartTime(long startTime) {
      this.startTime = startTime;
    }

    /**
     * @param endTime the endTime to set
     */
    public void setEndTime(long endTime) {
      this.endTime = endTime;
    }

    /**
     * @param destNodeNumber the destNodeNumber to set
     */
    public void setDestNodeNumber(int destNodeNumber) {
      this.destNodeNumber = destNodeNumber;
    }

    /**
     * @param sourcePort the sourcePort to set
     */
    public void setSourcePort(int sourcePort) {
      this.sourcePort = sourcePort;
    }

    /**
     * @param destPort the destPort to set
     */
    public void setDestPort(int destPort) {
      this.destPort = destPort;
    }

    /**
     * @param txRate the txRate to set
     */
    public void setTxRate(int txRate) {
      this.txRate = txRate;
    }
    
    /**
     * @param txRate the txRate to set
     */
    public void setTxRate2(int txRate) {
      this.txRate2 = txRate;
    }
  }
  
  public ScriptParams2() {

    int flowCnt = 1;
//    nodeConfigs = new NodeConfig[] {
//      new NodeConfig(1, 2, flowCnt++, accessCategorys.AC_VO, 20, ackPolicys.AP_NORMAL, 25 * Constants.SECOND, 40 * Constants.SECOND, 9000 + flowCnt, 9000 + flowCnt, 500),
//      new NodeConfig(1, 3, flowCnt++, accessCategorys.AC_VO, 20, ackPolicys.AP_NORMAL, 25 * Constants.SECOND, 40 * Constants.SECOND, 9000 + flowCnt, 9000 + flowCnt, 500),
//      new NodeConfig(2, 3, flowCnt++, accessCategorys.AC_VO, 20, ackPolicys.AP_NORMAL, 25 * Constants.SECOND, 40 * Constants.SECOND, 9000 + flowCnt, 9000 + flowCnt, 500),
//      new NodeConfig(4, 5, flowCnt++, accessCategorys.AC_VO, 20, ackPolicys.AP_NORMAL, 35 * Constants.SECOND, 50 * Constants.SECOND, 9000 + flowCnt, 9000 + flowCnt, 500),
//      new NodeConfig(2, 1, flowCnt++, accessCategorys.AC_VO, 20, ackPolicys.AP_NORMAL, 25 * Constants.SECOND, 40 * Constants.SECOND, 9000 + flowCnt, 9000 + flowCnt, 500)
//    };
    NodeConfig nc = new NodeConfig();
    nc.init(1, 2, flowCnt++, 20, 25 * Constants.SECOND, 40 * Constants.SECOND, 9000 + flowCnt, 9000 + flowCnt, 500, 500);
    nodeConfigs = new NodeConfig[] {nc};
    this.endTime = 100;
    this.seed = seed;
    this.nodes = nodeConfigs.length;
    this.assertion = true;
    this.dumpRadio = null;
    this.dumpFieldNam = null;
    this.dumpNet = true;
    this.seed = 2;
    if (true) {
      this.handlerFlow = true;
      this.handlerRadioLevel = DataManager.LEVEL_OFF;
      this.handlerFieldLevel = DataManager.LEVEL_BASIC;
      this.handlerFlowLevel = DataManager.LEVEL_ALL;
      this.handlerForwardGraphLevel = DataManager.LEVEL_IMPORTANT;
      this.handlerLinkQualityLevel = DataManager.LEVEL_IMPORTANT;
      this.handlerLinkTableLevel = DataManager.LEVEL_OFF;
      this.handlerMacLevel = DataManager.LEVEL_IMPORTANT;
      this.handlerMacTimeBarLevel = DataManager.LEVEL_OFF;
      this.handlerNetLevel = DataManager.LEVEL_OFF;
      this.handlerNetTimeBarLevel = DataManager.LEVEL_OFF;
      this.handlerRadioTimeBarLevel = DataManager.LEVEL_OFF;
      this.handlerRateLevel = DataManager.LEVEL_IMPORTANT;
      this.handlerRouteLevel = DataManager.LEVEL_OFF;
      this.handlerTXOPLevel = DataManager.LEVEL_OFF;
      this.handlerTransLevel = DataManager.LEVEL_OFF;
    } else {
      this.handlerRadioLevel = DataManager.LEVEL_ALL;
      this.handlerFieldLevel = DataManager.LEVEL_ALL;
      this.handlerFlowLevel = DataManager.LEVEL_ALL;
      this.handlerForwardGraphLevel = DataManager.LEVEL_ALL;
      this.handlerLinkQualityLevel = DataManager.LEVEL_ALL;
      this.handlerLinkTableLevel = DataManager.LEVEL_ALL;
      this.handlerMacLevel = DataManager.LEVEL_ALL;
      this.handlerMacTimeBarLevel = DataManager.LEVEL_ALL;
      this.handlerNetLevel = DataManager.LEVEL_ALL;
      this.handlerNetTimeBarLevel = DataManager.LEVEL_ALL;
      this.handlerRadioTimeBarLevel = DataManager.LEVEL_ALL;
      this.handlerRateLevel = DataManager.LEVEL_ALL;
      this.handlerRouteLevel = DataManager.LEVEL_ALL;
      this.handlerTXOPLevel = DataManager.LEVEL_ALL;
      this.handlerTransLevel = DataManager.LEVEL_ALL;
    }
    
    FieldBuilder.FieldParams field = new FieldBuilder.FieldParams();
    field.fieldX = 100;
    field.fieldY = 100;
    field.pathloss = new PathLossBuilder.FreeSpaceParams();
//    field.exponent = 2.7;
//    field.stdDeviation = 4.;
    field.spatial_mode = Constants.SPATIAL_LINEAR;
    this.field = field;

    RadioBuilder.NoiseParams radio = new RadioBuilder.NoiseAdditiveParams();
    radio.fieldX = field.fieldX;
    radio.fieldY = field.fieldY;
    radio.placement = Constants.PLACEMENT_RANDOM;
//    radio.placementOpts = "0.5x0.5x30x18";
    radio.useAnnos = true;
    this.node.radio = radio;

    MacBuilder.M802_11Params mac = new MacBuilder.M802_11Params();
    mac.useAnnos = radio.useAnnos;
    mac.useBitRateAnnos = false;
    RateBuilder.ConstantParams rate = new RateBuilder.ConstantParams();
    rate.controlBitrate = Constants.BANDWIDTH_6Mbps;
    rate.dataBitrate = Constants.BANDWIDTH_6Mbps;
    mac.rateSelection = rate;
    this.node.mac = mac;

    NetBuilder.IpParams net = new NetBuilder.IpParams();
    net.protocolMapper = new int[] { Constants.NET_PROTOCOL_UDP,
        Constants.NET_PROTOCOL_LINK_PROBE, Constants.NET_PROTOCOL_MCEXOR,
        Constants.NET_PROTOCOL_FLOODING };
    this.node.net = net;

    RouteBuilder.BrnDsrParams route = new RouteBuilder.BrnDsrParams();
    route.protocol = Constants.NET_PROTOCOL_MCEXOR;
    route.forwarding = brn.swans.Constants.FORWARDING_UNICAST;
    route.discovery = brn.swans.Constants.DISCOVERY_PROACTIVE;
    route.floodintOffset = 50000;
    route.floodingPeriod = 10000;
    route.floodingMax = 0;
    this.node.route = route;

    MetricBuilder.EtxParams metric = new MetricBuilder.EtxParams();
//    metric.rates = new int[] { 22 };
    metric.probes = new int[] { Constants.BANDWIDTH_6Mbps, 100 };
    metric.period = 1000;
    metric.tau = 30000;
    metric.globalLinkTable = true;
    route.metric = metric;
    
    rnd = new Random(this.seed);
  }

  /**
   * @return the nodeConfigs
   */
  public NodeConfig[] getNodeConfigs() {
    return nodeConfigs;
  }

  /**
   * @param nodeConfigs the nodeConfigs to set
   */
  public void setNodeConfigs(NodeConfig[] nodeConfigs) {
    this.nodeConfigs = nodeConfigs;
  }

  /**
   * @return the rnd
   */
  public Random getRnd() {
    return rnd;
  }

  public static void main(String[] args) {
    ScriptParams2 sp = new ScriptParams2();
    try {
      Util.writeObject("res/config/ScriptParams.xml", sp);
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
}
