package test.sim.scenario.mac;

import java.io.IOException;


import jist.swans.Constants;
import jist.swans.mac.MacInfo;
import jist.swans.misc.Util;
import brn.sim.AbstractParams;
import brn.sim.builder.Builder;
import brn.sim.builder.FieldBuilder;
import brn.sim.builder.MacBuilder;
import brn.sim.builder.MetricBuilder;
import brn.sim.builder.NetBuilder;
import brn.sim.builder.RadioBuilder;
import brn.sim.builder.PathLossBuilder.LogDistanceParams;
import brn.sim.builder.PathLossBuilder.ShadowingParams;
import brn.sim.builder.PathLossBuilder.DistShadowingParams;
import brn.sim.builder.RateBuilder;

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

	/** whether all nodes should probe the wires */
	public boolean singeSender = false;

	/** params for link probing */
	public Builder.Params metric = new MetricBuilder.EtxParams();

	/** constant bit-rates to test */
	public int[] bitrates = new int[] { Constants.BANDWIDTH_1Mbps };

	/** reference mac tx times */
	public MacTransmissionTimes txTimes = new MacTransmissionTimes(false,
			false, false, Constants.MAC_THRESHOLD_RTS);

	public MacTestParams() {
		/* handler */
	    this.handlerRadio = true;
	    this.handlerMac = true;
	    this.handlerNet = false;
	    this.handlerRoute = false;
	    this.handlerFlow = true;
	    this.handlerForwardGraph = true;
	    this.handlerLinkQuality = true;
	    this.handlerLinkTable = true;
	    this.handlerRadioTimeBar = true;
	    this.handlerMacTimeBar = true;

	    /* global */
	    this.endTime = 20000;
	    this.assertion = true;
	    this.seed = 1;
	    this.nodes = 2;//4;

	    this.singeSender = true;

	    MetricBuilder.EtxParams metric = new MetricBuilder.EtxParams();
	    metric.period = 1000;
	    metric.tau = 30000 / 4;
	    metric.probes = new int[] { Constants.BANDWIDTH_1Mbps, 1000,
	        Constants.BANDWIDTH_2Mbps, 1000, Constants.BANDWIDTH_5_5Mbps, 1000,
	        Constants.BANDWIDTH_11Mbps, 1000, };
	    metric.numberOfChannels = Constants.CHANNEL_NUMBER_DEFAULT;
	    this.metric = metric;

	    ShadowingParams shadow = new ShadowingParams();
      LogDistanceParams pathloss = new LogDistanceParams();
      pathloss.exponent = 2.7;
	    shadow.pathloss = pathloss;
	    shadow.stdDeviation = 8.;
	    shadow.coherenceTime = 1 * Constants.SECOND;

	    FieldBuilder.FieldParams field = new FieldBuilder.FieldParams();
	    field.fieldX = 150;
	    field.fieldY = 1;
	    field.spatial_mode = Constants.SPATIAL_LINEAR;
	    field.pathloss = shadow;
	    this.field = field;

	    RadioBuilder.NoiseParams radio = new RadioBuilder.NoiseAdditiveParams();
	    radio.fieldX = field.fieldX;
	    radio.fieldY = field.fieldY;
	    radio.placement = Constants.PLACEMENT_GRID;
	    radio.placementOpts = this.nodes + "x1";
	    radio.useAnnos = false;
	    radio.radioType = Constants.MAC_802_11bg;
	    this.node.radio = radio;

		MacBuilder.M802_11Params mac = new MacBuilder.M802_11Params();
		mac.useAnnos = radio.useAnnos;
		mac.useBitRateAnnos = false;
//		mac.macType = (short) radio.radioType;
		RateBuilder.ConstantParams rate = new RateBuilder.ConstantParams();
		rate.setControlBitrate(Constants.BANDWIDTH_1Mbps);
		rate.setDataBitrate(Constants.BANDWIDTH_1Mbps);
		mac.rateSelection = rate;
		this.node.mac = mac;

		NetBuilder.IpParams net = new NetBuilder.IpMacTestParams();
		net.protocolMapper = new int[] { Constants.NET_PROTOCOL_DUMB };
		this.node.net = net;

		// DumbParams route = new DumbParams();
		// route.protocol = Constants.NET_PROTOCOL_DUMB;
		// RouteBuilder.AodvParams route = new RouteBuilder.AodvParams();
		this.node.setRoute(/* route */null);
	}

	public static void main(String[] args) throws IOException {
		MacTestParams params = new MacTestParams();

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

	public MacTestParams setDbParams() {
		this.db = true;
		this.file = false;
		return this;
	}

	public MacTestParams setConstParams() {
		return setConstParams(Constants.BANDWIDTH_1Mbps,
				Constants.BANDWIDTH_1Mbps);
	}

	public MacTestParams setConstParams(int dataRate, int controlRate) {
		MacBuilder.M802_11Params mac = (MacBuilder.M802_11Params) this.node.mac;
		RateBuilder.ConstantParams rate = new RateBuilder.ConstantParams();
		rate.setControlBitrate(controlRate);
		rate.setDataBitrate(dataRate);
		mac.rateSelection = rate;
		return this;
	}

	public MacTestParams setArfParams() {
		MacBuilder.M802_11Params mac = (MacBuilder.M802_11Params) this.node.mac;
		RateBuilder.ArfParams rate = new RateBuilder.ArfParams();
//		rate.macType = mac.macType;
		mac.rateSelection = rate;
		return this;
	}
	
	public MacTestParams setAarfParams() {
		MacBuilder.M802_11Params mac = (MacBuilder.M802_11Params) this.node.mac;
		RateBuilder.AarfParams rate = new RateBuilder.AarfParams();
//		rate.macType = mac.macType;
		mac.rateSelection = rate;
		return this;
	}
	
	public MacTestParams setSampleParams() {
		MacBuilder.M802_11Params mac = (MacBuilder.M802_11Params) this.node.mac;
		RateBuilder.SampleParams rate = new RateBuilder.SampleParams();
//		rate.macType = mac.macType;
		mac.rateSelection = rate;
		return this;
	}
  
  public MacTestParams setAmrrParams() {
    MacBuilder.M802_11Params mac = (MacBuilder.M802_11Params) this.node.mac;
    RateBuilder.AmrrParams rate = new RateBuilder.AmrrParams();
//    rate.macType = mac.macType;
    mac.rateSelection = rate;
    return this;
  }
}
