'''
ant db-eval-jpy -Ddriver.class=res/test/SimHiddenNode.py -Ddriver.version=test
insert into simulation.progress (simulationId,state) values (6,'FINISHED')
sed -e 's/]];/]];...\n/g' |
sed -e 's/\[\]/\[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\]/g' |
sed -e 's/\],/\];/g'
'''

import sys
from math import ceil
from jarray import array, zeros
from java.lang import *
from java.util import *
from java.io import StringReader

from jist.swans import Constants
from jist.swans.net import NetAddress
from jist.swans.misc import Util

from brn.sim import *
from brn.sim.data import *
from brn.sim.builder import *
from brn.sim.handler import LinkQualityHandler
import brn.swans.Constants as BrnConstants

from brn.distsim.ormapper.util import *

true = 1
false = 0

NONE = DataManager.LEVEL_OFF
LESS = DataManager.LEVEL_IMPORTANT
BASIC = DataManager.LEVEL_BASIC
MORE = DataManager.LEVEL_ADDITIONAL
ALL = DataManager.LEVEL_ALL

class SimTcpTest(AbstractDriver):
    def __init__(self):
        pass

    #---------------------------------------------------------------------------
    # Driver Definition
    #---------------------------------------------------------------------------

    #def installHandlers(self, options):
    #  self.super__installHandlers(options)

      #linkQualityHandler = self.getDataManager().getContributor(LinkQualityHandler.ID)

      #if (None != linkQualityHandler and None != options.nodeParams[0].route):
      #  linkQualityHandler.setSampleLen(options.nodeParams[0].route.metric.tau / 1000)


#    def setupApplication(self, params, nodeId, node):
#        self.super__setupApplication(params,nodeId, node)
#
#        if not isinstance(params.nodeParams[0], NodeBuilder.AppParams):
#          return
#
#        appParams = AppBuilder.UdpNotifyParams()
#        appParams.start = 000
#        appParams.end = 250000
#        appParams.flowId = nodeId
#        #appParams.maxOutstandingPackets = -1
#        #params.nodeParams[0].flow.udpPayloadLen
#
#        if (nodeId <= params.nodeNumber[0]):
#            appParams.client = true
#            appParams.clientAddr = NetAddress(nodeId)
#            appParams.serverAddr = NetAddress(nodeId+params.nodeNumber[0])
#        else:
#            appParams.client = false
#            appParams.clientAddr = NetAddress(nodeId-params.nodeNumber[0])
#            appParams.serverAddr = NetAddress(nodeId)
#
#        builder = self.getBuilderProvider().getBuilder(appParams)
#        ret = builder.build(appParams, node)
#        self.getBuilderProvider().addHookUp(builder, appParams, node, ret)

    #---------------------------------------------------------------------------
    # Setup Parameter
    #---------------------------------------------------------------------------

    def getBerRadio(self):
        radio = RadioBuilder.NoiseAdditiveBerParams()
        radio.radioDesc = '''
          mac=802.11bg
          bitrates=6,9,12,18,24,36,48,54
          txpowers=19,19,19,19,19,18,16,15
          thresholds=5.4,5.8,7.0,9.5,11.3,14.9,18.6,20.6
          basicRates=6,12,24
          frequencies=2400
          frequency_spacings=5
          frequency_widths=20
          number_of_channels=1 '''
        radio.useAnnos = true
        radio.ccaModel = BrnConstants.RADIO_CCA_MODE1
        #nergyLevel_mW = Util.fromDB(-92.965 + .965);
        radio.ccaEnergyLevel_dBm = -91.44
        #nodeParams.radio.captureModel = BrnConstants.RADIO_CAPTURE_NONE;
        radio.captureEnergyLevel_dB = Util.fromDB(2);
        return radio

    def getThresholdRadio(self):
        radio = RadioBuilder.NoiseAdditiveParams()
        #radio = RadioBuilder.NoiseIndepParams()
        radio.radioDesc = '''
            sensitivity=-91.44
            ambient_noise=4.2516e-010
          mac=802.11bg
          bitrates=6,9,12,18,24,36,48,54
          txpowers=19,19,19,19,19,18,16,15
          thresholds=5.4,5.8,7.0,9.5,11.3,14.9,18.6,20.6
          basicRates=6,12,24
          frequencies=2400
          frequency_spacings=5
          frequency_widths=20
          number_of_channels=1 '''
        radio.useAnnos = true
        return radio

    def getReceiver(self,field, nodeParams):
        nodeParams.radio = self.getBerRadio()
        #nodeParams.radio = self.getThresholdRadio();
        nodeParams.radio.fieldX = field.fieldX
        nodeParams.radio.fieldY = field.fieldY
        #nodeParams.radio.placement = Constants.PLACEMENT_GRID
        #nodeParams.radio.placementOpts = "5x5"
        nodeParams.radio.placement = Constants.PLACEMENT_MANUAL
        nodeParams.radio.placementOpts = '282.494x210.4106: 86.2946x143.4466: 339.5293x17.039: 338.7066x130.8133: 221.6256x203.7057: 373.549x7.149: 112.6844x204.7621: 50.3338x2.0888: 71.4796x22.6795: 143.5478x179.6795: 307.5611x78.9896: 207.6851x49.8872: 296.736x236.8324: 209.0097x125.0367: 156.7916x210.9243: 60.1111x324.7711: 201.9642x193.8886: 99.2346x297.8131: 166.7675x343.3851: 114.7103x26.3367: 220.79x241.3338: 82.523x247.172: 263.299x326.1139: 321.3202x342.5137: 27.8487x170.7655: 134.8403x186.3928: 348.8375x69.289: 258.2174x99.6261: 341.7331x387.1084: 210.2313x154.4704: 357.3141x175.8907: 362.7455x268.9009: 344.0876x395.9033: 308.1311x246.5946: 11.4928x235.7724: 127.8575x362.1642: 208.1073x300.6962: 203.2921x341.8668: 140.1606x114.1046: 150.101x253.4018: 307.9187x351.2549: 88.591x63.1429: 20.7658x291.1235: 190.1405x54.8507: 32.5602x368.3264: 151.6639x29.2485: 91.0515x19.8032: 339.9184x59.5464: 352.4038x134.7987: 195.7055x114.442'

        # mac
        nodeParams.mac = MacBuilder.M802_11Params()
        #nodeParams.mac.macType = Constants.MAC_802_11g_PURE
        nodeParams.mac.useEifs = False
        nodeParams.mac.useAnnos = nodeParams.radio.useAnnos
        nodeParams.mac.useBitRateAnnos = true
        nodeParams.mac.rateSelection.dataBitrate = Constants.BANDWIDTH_6Mbps
        nodeParams.mac.rateSelection.controlBitrate = Constants.BANDWIDTH_6Mbps

        # net
        nodeParams.net = NetBuilder.IpNotifyParams()
        nodeParams.net.protocolMapper = array([ \
            Constants.NET_PROTOCOL_LINK_PROBE, \
            Constants.NET_PROTOCOL_UDP, \
            Constants.NET_PROTOCOL_TCP, \
            Constants.NET_PROTOCOL_MCEXOR, \
            Constants.NET_PROTOCOL_FLOODING, \
            Constants.NET_PROTOCOL_ARP \
          ], 'i')

        # route
        nodeParams.route = RouteBuilder.TableParams()
        nodeParams.route.protocol = Constants.NET_PROTOCOL_ARP

        # trans
        nodeParams.trans = TransBuilder.UdpParams()

        return nodeParams

    def getDsrNode(self,field, nodeParams):
      node = self.getReceiver(field, nodeParams)

      # rotue
      node.route = RouteBuilder.BrnDsrParams()
      node.route.protocol = Constants.NET_PROTOCOL_MCEXOR
      node.route.forwarding = BrnConstants.FORWARDING_UNICAST
      #node.route.forwarding = BrnConstants.FORWARDING_PASSIVEACK
      node.route.discovery = BrnConstants.DISCOVERY_PROACTIVE
      node.route.floodintOffset = 50000
      node.route.floodingPeriod = 10000
      node.route.floodingMax = 0
      node.route.bitrateFromLinkTable = false
      node.route.minLinkMetric = 50 * Constants.MILLI_SECOND

      # TODO staticroute

      node.route.metric = MetricBuilder.EttParams()
      node.route.metric.probes = array( [ \
                Constants.BANDWIDTH_6Mbps, 1500 \
          ] , 'i')
      node.route.metric.period = 1000
      node.route.metric.tau = 30000
      node.route.metric.globalLinkTable = true

      return node


    def envParams(self):
        params = AbstractParams()

        # general setup
        params.assertion = true
        params.endTime = 205
        params.seed = 1
        params.node = None

        # field
        params.field.fieldX = int(400)
        params.field.fieldY = int(400)
        params.field.spatial_mode = Constants.SPATIAL_HIER #SPATIAL_LINEAR
        #params.field.mobility = Constants.MOBILITY_BOUNDLESS_SIM_AREA
        # vMin:vMax:aMin:aMax:deltaT:maxAngularChange[:vStart:angStart]
        #params.field.mobilityOpts = "1:1:0:0:.5:0:1:0"
        #params.field.pathloss = PathLossBuilder.FreeSpaceParams()
        params.field.pathloss = PathLossBuilder.LogDistanceParams()
        params.field.pathloss.exponent = 3.5
        pathLoss = PathLossBuilder.ShadowingParams()
        pathLoss.pathloss = params.field.pathloss
        pathLoss.stdDeviation = 0.
        pathLoss.exponential = true
        pathLoss.coherenceTime = 1000 * Constants.MILLI_SECOND
        params.field.pathloss = pathLoss
        params.field.fading = FadingBuilder.NoneParams()
        #params.field.fading = FadingBuilder.PunnooseRicianParams()
        #params.field.fading.maxVelocity = 2.
        #params.field.fading.K = 12
        #params.field.fading = FadingBuilder.RicianParams()
        #params.field.fading.K = 6

        return params


    def dsrCbrParams(self):
        params = self.envParams()

        nodeParams =  NodeBuilder.FlowParams()
        nodeParams.flows = None
        nodeParams.trans = None

        params.nodeNumber = array( [50], 'i')
        params.nodeParams = array( [ self.getDsrNode(params.field, nodeParams)], \
                                     NodeBuilder.NodeParams)

        src = [6]#[33, 6, 45]
        dst = [45]#[8, 25, 32]
        flows = []
        for i in range(0,len(src)):
          flow = FlowBuilder.TcpParams()
          flow.flowId = i
          flow.start = 100000
          flow.tcpBytes = 1460 * 1000
          flow.clientAddr = NetAddress(src[i])
          flow.serverAddr = NetAddress(dst[i])
          flows += [flow]
        params.nodeParams[0].flows = array(flows, Builder.Params)
        nodeParams.trans = TransBuilder.TcpParams()

        return params


    #---------------------------------------------------------------------------
    # Scenario Definitions
    #---------------------------------------------------------------------------


    #---------------------------------------------------------------------------
    # Evaluation
    #---------------------------------------------------------------------------

    def runLocal(self):
      params = self.dsrCbrParams()

      level = BASIC
      params.handlerFieldLevel = level
      params.handlerRadioLevel = MORE
      params.handlerRadioDivLevel = LESS
      params.handlerMacLevel = ALL
      params.handlerRateLevel = level
      params.handlerNetLevel = MORE
      params.handlerRouteLevel= ALL
      params.handlerTransLevel = ALL
      params.handlerFlowLevel = ALL

      params.handlerRadioTimeBarLevel = NONE
      params.handlerMacTimeBarLevel = NONE
      params.handlerNetTimeBarLevel = NONE

      params.handlerForwardGraphLevel = level
      params.handlerLinkTableLevel = level
      params.handlerLinkQuality = NONE

      #params.dumpRadioNam = 'radio.nam';
      #params.dumpRadio = 'radio.tr';

      params.db = False
      #params.fileBinary = false
      #params.directory = "tmp"

      self.run(params)

    def runFile(self, fileName):
      params = Util.readObject(fileName);
      params.db=false

      params.handlerRadioTimeBarLevel = ALL
      params.handlerMacTimeBarLevel = ALL
      #params.handlerNetTimeBarLevel = level

      #params.handlerRadioDivLevel = LESS
      #params.handlerMacLevel = LESS
      #params.handlerFlowLevel = LESS

      self.run(params);

    def runTest(self, version):
      if "1" == version:
        params = self.dsrCbrParams()
      else:
        print "version " + version + " unknown"
        return

      level = BASIC
      params.handlerFieldLevel = level
      params.handlerRadioLevel = MORE
      params.handlerRadioDivLevel = LESS
      params.handlerMacLevel = ALL
      params.handlerRateLevel = level
      params.handlerNetLevel = MORE
      params.handlerRouteLevel= ALL
      params.handlerTransLevel = ALL
      params.handlerFlowLevel = ALL

      params.handlerRadioTimeBarLevel = NONE
      params.handlerMacTimeBarLevel = NONE
      params.handlerNetTimeBarLevel = NONE

      params.handlerForwardGraphLevel = level
      params.handlerLinkTableLevel = level
      params.handlerLinkQuality = NONE

      params.db = False

      self.run(params)

#---------------
# main
#---------------

if (1 < len(sys.argv)):
  driver = SimTcpTest()
  driver.run(array(sys.argv[1:], String))
