/*
 * Copyright (c) 1997 University of Southern California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *      This product includes software developed by the Information Sciences
 *      Institute of the University of Southern California.
 * 4. Neither the name of the University nor of the Institute may be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * @(#) $Header: /cvsroot/nsnam/nam-1/agent.cc,v 1.40 2011/11/02 16:08:03 tom_henderson Exp $ (LBL)
 */

#include <stdlib.h>

#ifdef WIN32
#include <windows.h>
#endif

#include "netview.h"
#include "psview.h"
#include "node.h"
#include "feature.h"
#include "agent.h"
#include "edge.h"
#include "paint.h"
#include "monitor.h"
#include "sincos.h"

static int g_agent_count = 1;  // Used to give unique id's to each agent

//----------------------------------------------------------------------
//  Wrapper for tcl creation of Agents 
//----------------------------------------------------------------------
static class AgentClass : public TclClass {
public:
  AgentClass() : TclClass("Agent") {} 

  TclObject * create(int argc, const char*const* argv) {
    Agent * agent;
    const char * type;
    int id;
    double size;

    type = argv[4];
    id  = strtol(argv[5], NULL, 10);
    size  = strtod(argv[6], NULL);

    agent = new BoxAgent(type, id, size);
    return agent;
  }
} class_agent;

//----------------------------------------------------------------------
//----------------------------------------------------------------------
Agent::Agent(const char * type, int id, double _size) :
  Animation(0, 0) {

  setDefaults();
  size(_size);

  label_ = new char[strlen(type) + 1];
  strcpy(label_, type);

  number_ = id;

  // Make sure new agents will have unique ids
  if (g_agent_count <= id) {
    g_agent_count = id + 1;
  }
}

//----------------------------------------------------------------------
// Agent::Agent(const char* name, double size)
//----------------------------------------------------------------------
Agent::Agent(const char* name, double _size) :
  Animation(0, 0),
  next_(0),
  node_(0),
  x_(0.0),
  y_(0.0),
  features_(NULL),
  edge_(NULL),
  angle_(NO_ANGLE),
  anchor_(0),
  mark_(0),
  color_(0),
  window_(20),
  windowInit_(1),
  maxcwnd_(0),
  packetSize_(210),
  interval_(0.0375),
  tracevar_(0),
  start_(0.0),
  stop_(10.0),
  produce_(0)
{
  size(_size);
  AgentPartner_ = NULL;
  flowcolor_ = NULL;
  flowcolor("black");

  number_ = g_agent_count;
  g_agent_count++;
  traffic_sources_ = NULL;
  label_ = new char[strlen(name) + 1];
  strcpy(label_, name);
  paint_ = Paint::instance()->thin();

  setDefaults();
}

//----------------------------------------------------------------------
//----------------------------------------------------------------------
void
Agent::setDefaults() {
  next_ = NULL;
  node_ = NULL;
  AgentPartner_ = NULL;
  x_ = 0.0;
  y_ = 0.0;
  features_ = NULL;
  edge_ = NULL;
  angle_ = NO_ANGLE;
  anchor_ = 0;
  mark_ = 0;
  color_ = NULL;

  window_ = 20;
  windowInit_ = 1;
  maxcwnd_ = 0;
  packetSize_ = 210;
  interval_ = 0.0375;
  tracevar_ = NULL;
  start_ = 0.0;
  stop_  = 1.0;
  produce_ = 0;

  flowcolor_ = NULL;
  flowcolor("black");

  traffic_sources_ = NULL;
  paint_ = Paint::instance()->thin();
  showLink();
}

float Agent::distance(float x, float y) const {
	return ((x_-x)*(x_-x) + (y_-y)*(y_-y));
}

void Agent::color(const char* name)
{
     if (name[0] == 0) {
          if (color_) {
	       delete []color_;
	       color_ = 0;
	  }
	  return;
     }

     if (color_)
       delete []color_;
     color_ = new char[strlen(name) + 1];
     strcpy(color_, name);
}

void Agent::size(double s)
{
	size_ = s;
  width_ = s;
  height_ = s;
	update_bb();
}

void Agent::update_bb() {
	double off = 0.5 * size_;
	/*XXX*/
	bb_.xmin = x_ - off;
	bb_.ymin = y_ - off;
	bb_.xmax = x_ + off;
	bb_.ymax = y_ + off;
}

//----------------------------------------------------------------------
// TrafficSource * 
// TrafficSource::addTrafficSource(TrafficSource * ts)
//   - Add traffic source to the trafficsources_ list
//   - Returns the traffic source before the one just added
//----------------------------------------------------------------------
TrafficSource * 
Agent::addTrafficSource(TrafficSource * ts) {
  TrafficSource * run, * last;

  run = traffic_sources_;
  last = NULL;

  // Find last traffic source on list
  while (run) {
    last = run;
    run = run->next_;
  }

  // if it exists then add it to the list
  if (last) {
    last->next_ = ts;
  } else {
    traffic_sources_ = ts;
  }  
  return last;
}

//----------------------------------------------------------------------
// TrafficSource *
// Agent::removeTrafficSource(TrafficSource * ts) {
//----------------------------------------------------------------------
TrafficSource *
Agent::removeTrafficSource(TrafficSource * ts) {
  // ts->previous_ should be NULL for the first traffic source
  // attached to this agent
  if (ts->previous_) {
    ts->previous_->next_ = ts->next_;
  } else {
    // I am the first traffic source so
    // make agent point to my next_
    traffic_sources_ = ts->next_;
  }

  if (ts->next_) {
    ts->next_->previous_ = ts->previous_;
  }

  return ts;
}

void Agent::add_feature(Feature* f) {
       f->next_ = features_;
       features_ = f;
}

Feature *Agent::find_feature(char *name) const
{
  /*given a feature, remove it from an agent's feature list*/
  Feature *ft;
  ft=features_;
  while (ft!=NULL)
    {
      if (strcmp(ft->name(), name)==0)
	return ft;
      ft=ft->next();
    }
  return NULL;
}
 

 
void Agent::delete_feature(Feature* r)
{
  /*given a feature, remove it from an agent's feature list*/
  Feature *f1, *f2;
  f1=features_;
  f2=features_;
  while ((f1!=r)&&(f1!=NULL))
    {
      f2=f1;
      f1=f1->next();
    }
  if (f1==r)
    {
      f2->next(f1->next());
      if (f1==features_)
	features_=f1->next();
    }
}
 

 
void Agent::label(const char* name, int anchor)
{
	delete label_;
	label_ = new char[strlen(name) + 1];
	strcpy(label_, name);
	anchor_ = anchor;
}

void Agent::drawlabel(View* nv) const
{
	/*XXX node number */
	if (label_ != 0)
		nv->string(x_, y_, size_, label_, anchor_);
}
/*
void Agent::drawlabel(PSView* nv) const
{
	if (label_ != 0)
		nv->string(x_, y_, size_, label_, anchor_);
}
*/

//----------------------------------------------------------------------
// void
// Agent::flowcolor(const char* color)
//----------------------------------------------------------------------
void
Agent::flowcolor(const char* color) {
 if (color[0] == 0) {
   if (flowcolor_) {
     delete []flowcolor_;
     flowcolor_ = 0;
   }
   return;
 }
       
 if (flowcolor_)
   delete []flowcolor_;

 flowcolor_ = new char[strlen(color) + 1];
 strcpy(flowcolor_, color);
}

void Agent::tracevar(const char* var)
{
        if (var[0] == 0) {
	       if (tracevar_) {
	              delete []tracevar_;
		      tracevar_ = 0;
	       }
	       return;
	}

        if (tracevar_)    delete []tracevar_;
	tracevar_ = new char[strlen(var) + 1];
	strcpy(tracevar_, var);
}

void Agent::reset(double)
{
	paint_ = Paint::instance()->thick();
}


void Agent::place(double x, double y) { 
	x_ = x;
	y_ = y;
	mark_ = 1;
	update_bb();
}

const char* Agent::info() const {
  static char text[128];

  if(AgentPartner_!=NULL) {
    sprintf(text, "Agent %s-%d\nConnected to: %s on Node %d",
                   name(), number(),
                   AgentPartner_->name(),
                   AgentPartner_->node_->num());
  } else {
    sprintf(text, "Agent: %s", label_);
  }
  return (text);
}

const char* Agent::getname() const
{
  static char text[128];
  sprintf(text, "a %s", label_);
  return (text);
}

void Agent::monitor(Monitor *m, double now, char *result, int len)
{
  char buf[256];
  Feature *f;
  monitor_=m;
  sprintf(result, "Agent: %s", label_);
  for(f=features_;f!=NULL;f=f->next()) {
    strcat(result, "\n");
    f->monitor(now, buf, 255);
    if (strlen(result)+strlen(buf)<(unsigned int)len)
      strcat(result, buf);
    else {
      fprintf(stderr, "not enough space for monitor return string\n");
      return;
    }
  }
}

//----------------------------------------------------------------------
// BoxAgent::BoxAgent(const char * type, int id, double size);
//----------------------------------------------------------------------
BoxAgent::BoxAgent(const char * type, int id, double size) :
  Agent(type,id,size) {
  BoxAgent::size(size);
}

//----------------------------------------------------------------------
// BoxAgent::BoxAgent(const char* name, double size)
//----------------------------------------------------------------------
BoxAgent::BoxAgent(const char* name, double size) :
  Agent(name, size) {
  BoxAgent::size(size);
}

//----------------------------------------------------------------------
// void
// BoxAgent::size(double s)
//----------------------------------------------------------------------
void
BoxAgent::size(double s) {
//  double delta = 0.5 * s;
  
  // Set size_ to s
  Agent::size(s);

 // x0_ = x_ - delta;
 // y0_ = y_ - delta;
 // x1_ = x_ + delta;
 // y1_ = y_ + delta;
 
  x0_ = x_;
  y0_ = y_;
//  x1_ = x_ + s;
//  y1_ = y_ + s*0.5;
  width_ = s;
  height_ = s*0.5;

 update_bb();
}

void BoxAgent::update_bb() {
	bb_.xmin = x0_;
	bb_.ymin = y0_;
	bb_.xmax = x0_ + width_;
	bb_.ymax = y0_ + height_;
}

//----------------------------------------------------------------------
//----------------------------------------------------------------------
void 
BoxAgent::findClosestCornertoPoint(double x, double y, double &corner_x,
                                   double &corner_y) const {
  double distance_0, distance_1;
  // Calculate the difference
  distance_0 = x0_ - x;
  distance_1 = x0_ + width_ - x;

  //We only want the magnitude
  if (distance_0 < 0) {
    distance_0 = -distance_0;
  }
  if (distance_1 < 0) {
    distance_1 = -distance_1;
  }
  if (distance_0 < distance_1) {
    corner_x = x0_;
  } else {
    corner_x = x0_ + width_;
  }

  // Do the same for the y values
  distance_0 = y0_ - y;
  distance_1 = y0_ + height_ - y;
  if (distance_0 < 0) {
    distance_0 = -distance_0;
  }
  if (distance_1 < 0) {
    distance_1 = -distance_1;
  }
  if (distance_0 < distance_1) {
    corner_y = y0_;
  } else {
    corner_y = y0_ + height_;
  }
}

//----------------------------------------------------------------------
//----------------------------------------------------------------------
int 
BoxAgent::inside(double, float px, float py) const {
	return (px >= x0_ && px <= (x0_ + width_) &&
		      py >= y0_ && py <= (y0_ + height_));
}

//----------------------------------------------------------------------
// void 
// BoxAgent::draw(View* nv, double ) const
//   - Draw the agent label with a rectangle around it
//   - Also draw monitors associated with it
//----------------------------------------------------------------------
void 
BoxAgent::draw(View* nv, double time) {
  double corner_x, corner_y, partner_corner_x, partner_corner_y;
  double label_width, label_height, label_x, label_y;
  char full_label[128];

  // Draw line connecting this to its partner
  if (AgentPartner_) {
    if (draw_link_) {
      AgentPartner_->findClosestCornertoPoint(x(), y(), 
                                        partner_corner_x, partner_corner_y);

      findClosestCornertoPoint(partner_corner_x, partner_corner_y,
                               corner_x, corner_y);
      nv->line(corner_x, corner_y, 
               partner_corner_x, partner_corner_y,
               paint_);
    }
  }
    
        
  // Draw the label if it exists
  if (label_ != 0) {
    // Exapnd label to show partner id if connected
    if (AgentPartner_) {
      if (AgentRole_ == SOURCE) {
        sprintf(full_label, "%s - %d", label_, number_);
      } else {
        sprintf(full_label, "%s - %d", label_, AgentPartner_->number());
      }

    } else {
      sprintf(full_label, "%s", label_);
    }

    // We have to keep calculting the label width and height because
    // we have no way of knowing if the user has zoomed in or out 
    // on the current network view.
    label_height = 0.9 * height_;
    label_width = nv->getStringWidth(full_label, label_height);

    // Add 10% of padding to width for the box
    setWidth(1.1 * label_width);

    place(x_,y_);
    
    // Center label in box
    label_x = x0_ + (width_ - label_width);
    label_y = y0_ + (height_ - label_height);

    nv->string(full_label, label_x , label_y, label_height, NULL);
    
    update_bb();
  }
  
  // Draw the rectangle 
  nv->rect(x0_, y0_, x0_ + width_, y0_ + height_, paint_);

  if (monitor_ != NULL) {
    monitor_->draw(nv, (x0_ + x0_ + width_)/2, y0_ - height_);
  }
}


/*
void BoxAgent::draw(PSView* nv, double ) const
{
  nv->rect(x0_, y1_, x1_, y0_, paint_);
  if (label_ != 0)
    {
      nv->string((x0_+x1_)/2, (y0_+y1_)/2, size_*0.75, label_, ANCHOR_CENTER);
    }
}
*/

//----------------------------------------------------------------------
// void 
// BoxAgent::place(double x, double y) {
//----------------------------------------------------------------------
void 
BoxAgent::place(double x, double y) {
  double nsin, ncos;
  Agent::place(x, y);  // Save original x,y values
  SINCOSPI(angle_, &nsin, &ncos);

  /*XXX should really use the X-display width*/
  //width_ = strlen(label_)/2;
  //width_ = strlen(label_) * 2.0;
  
  // on solaris, sin(M_PI) != 0 !!!
  
  // angle_ equals 0 or M_PI
  if ((nsin < 1.0e-8) && (nsin > -1.0e-9)) {
    y0_ = y_ - 0.5 * height_;
    //y_ = y0_;
  
  // angle is in the first 2 quadrants
  // i.e. between 0 and M_PI
  } else if (nsin > 0) {
    y0_ = y_;
   
  // angle_ is greater than M_PI but less than 2M_PI
  } else {
    // Move down twice as far to make room for traffic source labels
    y0_ = y_ - 2*height_;
    //y_ = y0_;
  }

  // angle equals M_PI/2 or 3M_PI/2 
  if ((ncos < 1.0e-8) && (ncos > -1.0e-9)) {
    x0_ = x_ - width_;
    //x_ = x0_;

  // angle is in 1st or 4th quadrant
  } else if (ncos > 0) {
    x0_ = x_;
  
  //  angle is in 2nd or 3rd quadrant
  //  i.e. between M_PI/2 and 3M_PI/2
  } else {
    x0_ = x_ - width_;
    //x_ = x0_;
  }

  update_bb();
}


//----------------------------------------------------------------------
// int
// Agent::writeNsDefinitionScript(FILE *file)
//----------------------------------------------------------------------
int
Agent::writeNsDefinitionScript(FILE *file) {
  TrafficSource * ts;

  // Create agent definition
  fprintf(file, "set agent(%d) [new Agent/%s]\n", number_, label_);
  // Attach it to it's parent node
  fprintf(file, "$ns attach-agent $node(%d) $agent(%d)\n",
                node_->num(), number_);

  if (AgentRole_ == SOURCE) {
    // Set flow color for agent
    fprintf(file, "\n$ns color %d \"%s\"\n", number_, flowcolor_);
    // flow id
    fprintf(file, "$agent(%d) set fid_ %d\n", number_, number_);
    // Packet Size
    fprintf(file, "$agent(%d) set packetSize_ %d\n", number_, packetSize_);

    if (strcmp(name(), "TCP") == 0) { 
      // Maximum window size
      fprintf(file, "$agent(%d) set window_ %d\n", number_, window_);
      // Initial reset of cwnd
      fprintf(file, "$agent(%d) set windowInit_ %d\n", number_, windowInit_);
      fprintf(file, "$agent(%d) set maxcwnd_ %d\n", number_, maxcwnd_);
      if (tracevar_) {
        if ((strcmp(tracevar_, "cwnd_") == 0) || 
            (strcmp(tracevar_, "ssthresh_") == 0)) {
          fprintf(file, "$ns add-agent-trace $agent(%d) tcp\n", number_);
          fprintf(file, "$ns monitor-agent-trace $agent(%d)\n", number_);
          fprintf(file, "$agent(%d) set tracevar_ %s\n", number_, tracevar_);
        }
      }
    } else if (strcmp(name(), "TCP/Reno") == 0) { 
    } else if (strcmp(name(), "TCP/NewReno") == 0) { 
    } else if (strcmp(name(), "TCP/Vegas") == 0) { 
    } else if (strcmp(name(), "TCP/Sack1") == 0) { 
    } else if (strcmp(name(), "TCP/Fack") == 0) { 
    } else if (strcmp(name(), "UDP") == 0) { 

    }
  } else if (AgentRole_ == DESTINATION) {
    // We have a sink
    if (strcmp(name(), "TCPSink") == 0) { 
      fprintf(file, "$agent(%d) set packetSize_ %d\n", number_, packetSize_);
    } else if (strcmp(name(), "TCPSink/DelAck") == 0) { 
      fprintf(file, "$agent(%d) set packetSize_ %d\n", number_, packetSize_);
      fprintf(file, "$agent(%d) set interval_ %f\n", number_, interval_);
    } else if (strcmp(name(), "TCPSink/Sack1") == 0) {
     // Ask about this one look at ns doc 29.2.3 for proper 
     // syntax
    }
    // if it is NULL or anything else do nothing
  }

  
   /*
  // CBR source agents
    } else if (strcmp(name(), "CBR")==0) {
      fprintf(file, "\n$ns color %d \"%s\"\n",number_, flowcolor_);
      fprintf(file, "set agent%d [new Agent/%s]\n", number_, label_);
      fprintf(file, "$ns attach-agent $n(%d) $agent%d \n", node_->num(), number_);
      fprintf(file, "$agent%d set fid_ %d\n", number_, number_);
      fprintf(file, "$agent%d set packetSize_ %d\n", number_, packetSize_);
      fprintf(file, "$agent%d set interval_ %f\n", number_, interval_);

  } else if (AgentRole_ == DESTINATION) {
    // TCP/Full destination agents 
    } else if (strcmp(name(), "TCP/FullTcp") == 0){
      fprintf(file, "\nset agent%d [new Agent/%s]\n", number_, label_);
      fprintf(file, "$ns attach-agent $node(%d) $agent%d \n", node_->num(), number_);
      fprintf(file, "$agent%d listen\n", number_);

    // all destination agents (NULL)
    } else {
      fprintf(file, "\nset agent%d [new Agent/%s]\n", number_, label_);
      fprintf(file, "$ns attach-agent $node(%d) $agent%d\n", node_->num(), number_);
    }
  }
*/
  if (traffic_sources_) {
      // # Create a CBR traffic source and attach it to udp0
      // set cbr0 [new Application/Traffic/CBR]
      // $cbr0 set packetSize_ 500
      // $cbr0 set interval_ 0.005
      // $cbr0 attach-agent $udp0
    fprintf(file, "\n# Create traffic sources and add them to the agent.\n");
    for (ts = traffic_sources_; ts; ts = ts->next_) {
      ts->writeNsDefinitionScript(file);
    }
  }

  return 0;
}

//----------------------------------------------------------------------
// int
// Agent::writeNsConnectionScript(FILE * file)
//----------------------------------------------------------------------
int
Agent::writeNsConnectionScript(FILE * file) {
  TrafficSource * ts;

  if (AgentRole_ == SOURCE) {
    fprintf(file, "$ns connect $agent(%d) $agent(%d)\n\n", 
                  number_, AgentPartner_->number_);

    fprintf(file, "\n# Traffic Source actions.\n");
    for (ts = traffic_sources_; ts; ts = ts->next_) {
      ts->writeNsActionScript(file);
    }
  }
  return 0;
}

//----------------------------------------------------------------------
//
//----------------------------------------------------------------------
int Agent::saveAsEnam(FILE *file) {
  if ((AgentRole_ == 10)&&(strcmp(name(), "CBR")!=0)) {
    if (AgentPartner_ != NULL) 
      fprintf(file, "##g -t * -l %s -r %d -s %d -c %s -i %d -w %d -m %d -t %s -b %f -p %d -o %f -n %d -u %d\n",
          label_, AgentRole_, node_->num(), flowcolor_, windowInit_, window_, 
          maxcwnd_, tracevar_, start_, produce_, stop_, number_, 
          AgentPartner_->number_);
    else 
      fprintf(file, "##g -t * -l %s -r %d -s %d -c %s -i %d -w %d -m %d -t %s -b %f -p %d -o %f -n %d\n",
          label_, AgentRole_, node_->num(), flowcolor_, windowInit_, window_,
          maxcwnd_, tracevar_, start_, produce_, stop_, number_);


  } else if (((AgentRole_ == SOURCE) || 
              (AgentRole_ == 10)) &&
             (strcmp(name(), "CBR")==0)) {
    if (AgentPartner_ != NULL)
      fprintf(file, "##g -t * -l %s -r %d -s %d -c %s -k %d -v %f -b %f -o %f -n %d -u %d \n",
           label_, AgentRole_, node_->num(), flowcolor_, packetSize_, 
           interval_, start_, stop_, number_, AgentPartner_->number_);
    else 
      fprintf(file, "##g -t * -l %s -r %d -s %d -c %s -k %d -v %f -b %f -o %f -n %d\n",
           label_, AgentRole_, node_->num(), flowcolor_, packetSize_,
           interval_, start_, stop_, number_);

  } else {
    if (AgentPartner_ != NULL)
      fprintf(file, "##g -t * -l %s -r %d -s %d -n %d -u %d \n",
                    label_, AgentRole_, node_->num(), number_,
                    AgentPartner_->number_);
    else 
      fprintf(file, "##g -t * -l %s -r %d -s %d -n %d\n",
                    label_, AgentRole_, node_->num(), number_);
  }
  return(0);
}

//----------------------------------------------------------------------
//----------------------------------------------------------------------
const char* Agent::property() {

  static char text[256];
  char * p;

  // Header
  p = text;
  sprintf(text, "{\"Agent: %s-%d\" title title \"Agent %d\"} ",
                name(), number_, number_);

  if (AgentRole_ == SOURCE) {
    p = &text[strlen(text)];
    sprintf(p, "{\"Flow Color\" flowcolor_ color %s} ", flowcolor_);
    p = &text[strlen(text)];
    sprintf(p, "{\"Packet Size\" packetSize_ text %d} ", packetSize_);
    
    //TCP source agents
    if (strcmp(name(), "TCP") == 0) {
      p = &text[strlen(text)];
      sprintf(p, "{\"Initial Window Size\" windowInit_ text %d} ", windowInit_);
      p = &text[strlen(text)];
      sprintf(p, "{\"Window\" window_ text %d} ", window_); 
      p = &text[strlen(text)];
      sprintf(p, "{\"Max Cwnd\" maxcwnd_ text %d} ", maxcwnd_);
    } 

  } else if (AgentRole_ == DESTINATION) {
    p = &text[strlen(text)];
    sprintf(p, "{\"Partner\" partner_number text %d} ", AgentPartner_->num());
  } else {
    p = &text[strlen(text)];
    sprintf(p, "{\"To edit this agent's properties connect agent to it's partner.\" partner_number label  }");
  }

  return(text);
}
