#include <graph_displayer_canvas.h>
#include <broken_edge.h>
#include <math.h>


int GraphDisplayerCanvas::changeNodeRadius (std::string mapname, Graph::Node node)
{
  Graph::NodeMap<double> * actual_map;
  if(mapname=="Default")
    {
      actual_map=new Graph::NodeMap<double>(g,node_property_defaults[N_RADIUS]);
    }
  else
    {
      actual_map=(mapstorage.nodemap_storage)[mapname];
    }

  if(node==INVALID)
    {
      for (NodeIt i(g); i!=INVALID; ++i)
	{
	  int w=(int)(*actual_map)[i];
	  if(w>=0)
	    {
	      double x1, y1, x2, y2;
	      x1=nodesmap[i]->property_x1().get_value();
	      x2=nodesmap[i]->property_x2().get_value();
	      y1=nodesmap[i]->property_y1().get_value();
	      y2=nodesmap[i]->property_y2().get_value();
	      nodesmap[i]->property_x1().set_value((x1+x2)/2-w);
	      nodesmap[i]->property_x2().set_value((x1+x2)/2+w);
	      nodesmap[i]->property_y1().set_value((y1+y2)/2-w);
	      nodesmap[i]->property_y2().set_value((y1+y2)/2+w);
	    }
	}
    }
  else
    {
      //I think only new nodes use this case
//       int w=(int)(*actual_map)[node];
      int w=(int)(node_property_defaults[N_RADIUS]);
      if(w>=0)
	{
	  double x1, y1, x2, y2;
	  x1=nodesmap[node]->property_x1().get_value();
	  x2=nodesmap[node]->property_x2().get_value();
	  y1=nodesmap[node]->property_y1().get_value();
	  y2=nodesmap[node]->property_y2().get_value();
	  nodesmap[node]->property_x1().set_value((x1+x2)/2-w);
	  nodesmap[node]->property_x2().set_value((x1+x2)/2+w);
	  nodesmap[node]->property_y1().set_value((y1+y2)/2-w);
	  nodesmap[node]->property_y2().set_value((y1+y2)/2+w);
	}
    }
  return 0;
};

int GraphDisplayerCanvas::changeNodeColor (std::string mapname, Graph::Node node)
{  

  //function maps the range of the maximum and
  //the minimum of the nodemap to the range of
  //green in RGB

  Graph::NodeMap<double> * actual_map;
  if(mapname=="Default")
    {
      actual_map=new Graph::NodeMap<double>(g,node_property_defaults[N_COLOR]);
    }
  else
    {
      actual_map=(mapstorage.nodemap_storage)[mapname];
    }

  double max, min;

  if(mapname!="Default")
    {
      max=mapstorage.maxOfNodeMap(mapname);
      min=mapstorage.minOfNodeMap(mapname);
    }
  else
    {
      max=node_property_defaults[N_COLOR];
      min=node_property_defaults[N_COLOR];
    }


  if(node==INVALID)
    {

      for (NodeIt i(g); i!=INVALID; ++i)
	{
	  Gdk::Color color;

	  double w=(*actual_map)[i];

	  if(max!=min)
	    {
	      color.set_rgb_p (0, 0, 100*(w-min)/(max-min));
	    }
	  else
	    {
	      color.set_rgb_p (0, 0, 100);
	    }

	  nodesmap[i]->property_fill_color_gdk().set_value(color);
	}
    }
  else
    {
      Gdk::Color color;

      double w=(*actual_map)[node];

      if(max!=min)
	{
	  color.set_rgb_p (0, 0, 100*(w-min)/(max-min));
	}
      else
	{
	  color.set_rgb_p (0, 0, 100);
	}

      nodesmap[node]->property_fill_color_gdk().set_value(color);
    }
  return 0;
};

int GraphDisplayerCanvas::changeNodeText (std::string mapname, Graph::Node node)
{

  //the number in the map will be written on the node
  //EXCEPT when the name of the map is Text, because
  //in that case empty string will be written, because
  //that is the deleter map

  Graph::NodeMap<double> * actual_map=NULL;
  if(mapname!="Default")
    {
      actual_map=(mapstorage.nodemap_storage)[mapname];
    }

  if(node==INVALID)
    {
      for (NodeIt i(g); i!=INVALID; ++i)
	{
	  if(mapname!="Default")
	    {
	      nodemap_to_edit=mapname;
	      double number=(*actual_map)[i];
	      int length=1;
	      //if number is smaller than one, length would be negative, or invalid
	      if(number>=1)
		{
		  length=(int)(floor(log(number)/log(10)))+1;
		}
	      int maxpos=(int)(pow(10,length-1));
	      int strl=length+1+RANGE;
	      char * str=new char[strl];
	      str[length]='.';
	      str[strl]='\0';
      
	      for(int j=0;j<strl;j++)
		{
		  if(j!=length)
		    {
//  		      std::cout << (number) << "-" << (int)number << "=" << (number)-(int)number << std::endl;
		      if((number-(int)number)>ALMOST_ONE)
			{
// 			  std::cout<<"rounding: " <<number<<std::endl;
			  number=round(number);
			}
 		      int digit=(int)(number/maxpos);
// 		      std::cout << number << "/" << maxpos << "=" << digit << std::endl;
		      str[j]=(digit+'0');
		      number-=digit*maxpos;
		      number*=10;
		    }
		}
      
	      nodetextmap[i]->property_text().set_value(str);
	    }
	  else
	    {
	      nodemap_to_edit="";
	      nodetextmap[i]->property_text().set_value("");
	    }
	}
    }
  else
    {
      if(mapname!="Default")
	{
	  double number=(*actual_map)[node];
	  int length=1;
	  //if number is smaller than one, length would be negative, or invalid
	  if(number>=1)
	    {
	      length=(int)(floor(log(number)/log(10)))+1;
	    }
	  int maxpos=(int)(pow(10,length-1));
	  int strl=length+1+RANGE;
	  char * str=new char[strl];
	  str[length]='.';
	  str[strl]='\0';
      
	  for(int j=0;j<strl;j++)
	    {
	      if(j!=length)
		{
		  if((number-(int)number)>ALMOST_ONE)
		    {
		      number=round(number);
		    }
		  int digit=(int)(number/maxpos);
		  str[j]=(digit+'0');
		  number-=digit*maxpos;
		  number*=10;
		}
	    }
      
	  nodetextmap[node]->property_text().set_value(str);
	}
      else
	{
	  nodetextmap[node]->property_text().set_value("");
	}
    }
  return 0;
};
