package test.brn.gateway;

import jist.swans.Constants;
import jist.swans.misc.Util;
import jist.swans.net.NetAddress;
import brn.sim.AbstractParams;
import brn.sim.builder.FlowBuilder;
import brn.sim.builder.FieldBuilder;
import brn.sim.builder.MacBuilder;
import brn.sim.builder.NetBuilder;
import brn.sim.builder.RadioBuilder;
import brn.sim.builder.RateBuilder;
import brn.sim.builder.RouteBuilder;
import brn.sim.builder.TransBuilder;
import brn.sim.builder.FlowBuilder.FlowParams;
import brn.sim.builder.NodeBuilder.NodeParams;
import brn.sim.builder.PathLossBuilder.DistShadowingParams;
import brn.sim.builder.TransBuilder.TransParams;
import click.sim.builder.ClickBuilder;

public class GatewayParams extends AbstractParams {
  private static final long serialVersionUID = 1L;

  public static final int ETH_BASE_OFFSET = 1024;

  //public TrafficBuilder.TrafficParams trafficParams = new TrafficBuilder.HorizontalParams();
  public FlowBuilder.FlowParams flowParams = new FlowBuilder.CbrUdpParams();
  
  public TransBuilder.TransParams transParams = new TransBuilder.UdpParams();

  /** the super gateway node */
  public NodeParams internetNode = null;
  public int internetNodeId = 1 + GatewayParams.ETH_BASE_OFFSET;

  /** number of clients (STAs) */
  public int clients = 0;
  /** the client node */
  public NodeParams clientNode = null;
  

  /**
   * Creates default parameters for TxDOR simulation.
   *
   * @return default parameters for TxDOR simulation.
   */
  public static GatewayParams defaultParams(GatewayParams params) throws Exception {
    params.nodes = 10;
    params.clients = 1;
    params.endTime = 130;
    params.seed = 2;

    // set parameters
    params.nodesStart = 2;
    params.assertion = true;

    DistShadowingParams pathLoss = new DistShadowingParams();
    pathLoss.exponent = 2.7;
    pathLoss.stdDeviation = 4.;
    pathLoss.coherenceTime = 0 * Constants.SECOND;

    FieldBuilder.FieldParams field = new FieldBuilder.FieldParams();
//    field.spatial_mode = Constants.SPATIAL_LINEAR; // TODO HIER
    field.fieldX = 2400;
    field.fieldY = 2400;
    field.pathloss = pathLoss;
    params.field = field;

    {
      RadioBuilder.NoiseParams radio = new RadioBuilder.NoiseAdditiveTxDivParams();
      radio.fieldX = field.fieldX;
      radio.fieldY = field.fieldY;
      radio.useAnnos = true;
      params.node.radio = radio;

      radio.placement = Constants.PLACEMENT_RANDOM;
//      radio.placementOpts = "2x2";
      radio.min_connectivity_betweenNodes = 2;
      radio.connectivityBitRate = Constants.BANDWIDTH_11Mbps;

      ClickBuilder.MacParams mac = new ClickBuilder.MacParams();
      mac.useAnnos = radio.useAnnos;
      mac.useBitRateAnnos = true;
      ((RateBuilder.ConstantParams)mac.rateSelection).dataBitrate = Constants.BANDWIDTH_11Mbps;
      params.node.mac = mac;
      
      ClickBuilder.HostNetParams net = new ClickBuilder.HostNetParams();
      net.protocolMapper = new int[] { Constants.NET_PROTOCOL_UDP,
          Constants.NET_PROTOCOL_LINK_PROBE, Constants.NET_PROTOCOL_AODV,
          Constants.NET_PROTOCOL_FLOODING, Constants.NET_PROTOCOL_DSR };
      net.clickfile = "res/click/gateway.click";
      net.wireMacBase = ETH_BASE_OFFSET;
      params.node.net = net;

      params.node.route = new RouteBuilder.AodvParams();
    }
    
    {
      params.clientNode = (NodeParams) params.node.clone();
      
      ClickBuilder.MacParams mac = (ClickBuilder.MacParams) params.clientNode.mac;
      mac.isStation = true;
      
      ClickBuilder.NetParams net = new ClickBuilder.NetParams();
      net.protocolMapper = new int[] { Constants.NET_PROTOCOL_UDP };
      net.clickfile = "res/click/clientnode.click";
      params.clientNode.net = net;
      params.clientNode.route = null;
    }
    
    {
      params.internetNode = new NodeParams();
      params.internetNode.radio = new RadioBuilder.NoiseIndepParams();
      params.internetNode.mac = new MacBuilder.DumbParams();
      params.internetNode.net = new NetBuilder.IpParams();
      ((NetBuilder.IpParams)params.internetNode.net).protocolMapper = 
        ((NetBuilder.IpParams)params.node.net).protocolMapper;
      params.internetNode.route = new RouteBuilder.AodvParams();
    }

    /*
    TrafficBuilder.RadialParams trafficParams = new TrafficBuilder.RadialParams();
    trafficParams.flowParams = params.trafficParams.flowParams;
    trafficParams.startAngle = .75 * Math.PI;
    params.trafficParams = trafficParams;

    ((AppBuilder.UdpNotifyParams)params.trafficParams.flowParams).start = 80000;
    ((AppBuilder.UdpNotifyParams)params.trafficParams.flowParams).end = 90000;
    ((AppBuilder.UdpCaParams)params.trafficParams.flowParams).maxOutstandingPackets = 180;
    */
    
    FlowBuilder.CbrUdpParams flowParams = (FlowBuilder.CbrUdpParams)params.flowParams;
    flowParams.start = 80000;
    flowParams.end = 90000;
    flowParams.serverAddr = new NetAddress(params.internetNodeId);
    flowParams.clientAddr = new NetAddress(params.nodes + params.nodesStart);
//    ((AppBuilder.UdpParams)params.flowParams).maxNumberOfPackets = 1;
    
    ((ClickBuilder.NetParams)params.node.net).clickGui = true;
    params.dumpNet = true;
    params.dumpMac = false;
//    params.dumpMacNam = "out.nam";
    
    params.handlerRadio = true;
    params.handlerRadioEx = true;
    params.handlerMac = true;
    params.handlerNet = true;
    params.handlerRoute = true;
    params.handlerTrans = true;
    params.handlerFlow = true;
    
    params.handlerForwardGraph = true;
    params.handlerLinkTable = true;
    params.handlerLinkQuality = true;
    
    params.handlerRadioTimeBar = true;
    params.handlerMacTimeBar = true;
    params.handlerNetTimeBar = true;
    
    return params;
  }

  /**
   * Set parameters for batch execution with distsim.
   *
   * @return the parameters to adopt
   */
  public GatewayParams setParamsBatch() {
    GatewayParams params = this;

    params.handlerRadio = false; // too big
    params.handlerRadioEx = false; // too big, to slow
    params.handlerMac = true;
    params.handlerNet = true;
    params.handlerRoute = true;
    params.handlerFlow = true;
    params.handlerForwardGraph = true;
    params.handlerLinkQuality = false; // too big
    params.handlerLinkTable = true;
    params.handlerRadioTimeBar = false;  // too big
    params.handlerMacTimeBar = false;  // too big
    params.handlerNetTimeBar = false;  // too big

    params.dumpRadio = null;//"txdor.tr";
    params.dumpMac = false;
    params.dumpNet = false;
    params.dumpFieldNam = null;//"txdor-field.nam";
    params.dumpRadioNam = null;//"txdor-radio.nam";
    params.dumpMacNam = null;//"txdor-mac.nam";
    params.dumpNetNam = null;//"txdor-net.nam";

    return params;
  }

  /**
   * Set parameters for local test execution.
   *
   * @return the parameters to adopt
   */
  public GatewayParams setParamsTest() {
    GatewayParams params = this;

    params.db = true;
    params.dbRes = "jdbc:mysql://localhost:3306/simulation";
    params.dbDef = "jdbc:mysql://localhost:3306/simulation";
    params.file = false;
    params.directory = "/tmp/sim";

    params.handlerRadio = false;
    params.handlerRadioEx = false;
    params.handlerMac = true;
    params.handlerNet = true;
    params.handlerRoute = true;
    params.handlerFlow = true;
    params.handlerForwardGraph = true;
    params.handlerLinkQuality = false;
    params.handlerLinkTable = true;
    params.handlerRadioTimeBar = false;  // too big
    params.handlerMacTimeBar = false;  // too big
    params.handlerNetTimeBar = false;  // too big

    params.dumpRadio = null;//"txdor.tr";
    params.dumpMac = false;
    params.dumpNet = false;
    params.dumpFieldNam = null;//"txdor-field.nam";
    params.dumpRadioNam = null;//"txdor-radio.nam";
    params.dumpMacNam = null; //"txdor-mac.nam";
    params.dumpNetNam = null;  //"txdor-net.nam";

    return params;
  }

  public static void main(String[] args) throws Exception {
    GatewayParams params = defaultParams(new GatewayParams()).setParamsTest();
//    TxDOrParams params = aodvParams();
//    TxDOrParams params = unicastParams();


    // and out
    Util.writeObject("res/config/TxDOrParams.xml", params);
  }


//  public AppBuilder.UdpNotifyParams getAppParams() {
//    return appParams;
//  }
//
//  public void setAppParams(AppBuilder.UdpNotifyParams appParams) {
//    this.appParams = appParams;
//  }

  /*
  public TrafficBuilder.TrafficParams getTrafficParams() {
    return trafficParams;
  }

  public void setTrafficParams(TrafficBuilder.TrafficParams trafficParams) {
    this.trafficParams = trafficParams;
  }
  */

  public TransBuilder.TransParams getTransParams() {
    return transParams;
  }

  public void setTransParams(TransBuilder.TransParams transParams) {
    this.transParams = transParams;
  }

  /* (non-Javadoc)
   * @see brn.sim.AbstractParams#clone()
   */
  public Object clone() throws CloneNotSupportedException {
	GatewayParams ret = (GatewayParams) super.clone();
    if (null != flowParams) ret.flowParams = (FlowParams) flowParams.clone();
    if (null != transParams) ret.transParams = (TransParams) transParams.clone();
    return ret;
  }

  public FlowBuilder.FlowParams getFlowParams() {
    return flowParams;
  }

  public void setFlowParams(FlowBuilder.FlowParams flowParams) {
    this.flowParams = flowParams;
  }

  public NodeParams getInternetNode() {
    return internetNode;
  }

  public void setInternetNode(NodeParams internetNode) {
    this.internetNode = internetNode;
  }

  public int getClients() {
    return clients;
  }

  public void setClients(int clients) {
    this.clients = clients;
  }

  public NodeParams getClientNode() {
    return clientNode;
  }

  public void setClientNode(NodeParams clientNode) {
    this.clientNode = clientNode;
  }

  public int getInternetNodeId() {
    return internetNodeId;
  }

  public void setInternetNodeId(int internetNodeId) {
    this.internetNodeId = internetNodeId;
  }

}
