// Copyright (C) 2001 Jean-Marc Valin

#include <iostream>
#include "GUINetTerminal.h"
#include "GUITerminal.h"
#include "GUINode.h"
#include "GUINetwork.h"
#include "UIDocument.h"
#include "misc_gui.h"

using namespace std;

namespace FD {

static void create_net_terminal(gchar * str, GUINetTerminal *term)
{

   //cout<<"create_net_terminal"<<endl;

   if (str)
      term->setName(string(str));
   else 
      term->setName("");
}

static gint net_terminal_handler (GnomeCanvasItem *item, GdkEvent *event, gpointer data)
{
   //cerr << "caught button\n";
   return ((GUINetTerminal *)(data))->event(event);
}

GUINetTerminal::GUINetTerminal(UITerminal *_terminal, NetTermType _type, const string &_name,
			       const string &_objType, const string &_description)
  : UINetTerminal(_terminal, _type, _name, _objType, _description)
   , item(NULL)
{

  //cerr<<"NetTerminal constructor type : "<<_type<<endl;

   string defaultName;
   string prompt;
   gint anchor;
   
   terminal->getItemPos(x,y);
   const char *color;
   if (type == INPUT)
   {
     //defaultName = "INPUT";
     //defaultName = terminal->getName();
     defaultName = find_unique_name(terminal->getName(), _type);
     prompt = "Input name?";
     anchor = GTK_ANCHOR_EAST;
     x -= 10;
     color="red";
   }   
   else if (type == OUTPUT) {
     //defaultName = "OUTPUT";
     //defaultName = terminal->getName();
     defaultName = find_unique_name(terminal->getName(),_type);
     prompt = "Output name";
     anchor = GTK_ANCHOR_WEST;
     x += 10;
     color="blue";
   }   
   else if (type == CONDITION) {
     defaultName = "CONDITION";
     anchor = GTK_ANCHOR_WEST;
     x += 10;
     color="purple";
   }
   
   if (name == "") {

     //set the default object_type and description
     setObjectType(terminal->getType());
     setDescription(terminal->getDescription());


     //prompting user for input
     name = ask_string_dialog(prompt.c_str(), defaultName.c_str());
   }
   
   //find network duplicate terminal names 
   //Dominic Letourneau Feb 1 2002.

   //vector<string> my_terms = terminal->getNode()->getNetwork()->getTerminals(_type);
   //int count = 0;

   vector<UINetTerminal*> my_terminals = terminal->getNode()->getNetwork()->getTerminals();

   for (unsigned int i = 0; i < my_terminals.size(); i++) {
     if (my_terminals[i]->getName() == name 
	 && my_terminals[i] != static_cast<UINetTerminal*>(this)
	 && my_terminals[i]->getType() == type) {
       
       cerr<<"*WARNING* duplicate terminal name : "<<name<<endl;
       
       if (type == INPUT || type == OUTPUT) {
	 //updating input/output
	 cerr<<"*WARNING* input/output removed from node : "<<my_terminals[i]->getTerminal()->getNode()->getName()<<endl;
	 my_terminals[i]->getTerminal()->disconnectNetTerminal();
	 delete my_terminals[i]; //safe ?
       }
       if (type == CONDITION) {
	 cerr<<"*WARNING* input/output removed from node : "<<my_terminals[i]->getTerminal()->getNode()->getName()<<endl;
	 my_terminals[i]->getTerminal()->disconnectNetTerminal();
	 delete my_terminals[i]; //safe ?
       } 
     }
   }




   //FIXME: Is this dangerous? I don't know. But it's ugly at best
   if (name == "")
   {
      //cerr << "aborted\n";
      terminal->getNode()->getNetwork()->removeTerminal(this);
      //cerr << "disconnecting\n";
      terminal->disconnectNetTerminal();
      //cerr << "throwing\n";
      //throw false;
      //cerr<< "returning"<<endl;
      //Now, it doesn't leak, but it's really ugly
      delete this;
      return;
      
   }

   if (type ==OUTPUT || type == INPUT) {
     terminal->getNode()->getNetwork()->interfaceChangeNotify();
     UIDocument *doc = terminal->getNode()->getNetwork()->getDocument();
     doc->updateAllSubnetTerminals(terminal->getNode()->getNetwork()->getName(),getName(),getType(),false);
   }
   item = gnome_canvas_item_new(dynamic_cast<GUINode *>(terminal->getNode())->getGroup(),
                         gnome_canvas_text_get_type(),
                         "x", x,
                         "y", y,
                         "text", name.c_str(),
                         "anchor", anchor ,
                         "fill_color", color,
                         "font", "sans 10",
                         NULL);

   gtk_signal_connect(GTK_OBJECT(item), "event",
                      (GtkSignalFunc) net_terminal_handler,
                      this);

}


GUINetTerminal::~GUINetTerminal()
{
  UIDocument *doc = terminal->getNode()->getNetwork()->getDocument();
  doc->updateAllSubnetTerminals(terminal->getNode()->getNetwork()->getName(),getName(),getType(),true);

  if (item) {
    gtk_object_destroy(GTK_OBJECT(item));
  }
}


gint GUINetTerminal::event(GdkEvent *event)
{
   //return TRUE;
   switch (event->type) 
   {
   case GDK_BUTTON_PRESS:
      switch(event->button.button) 
      {
      case 1:
         if (event->button.state & GDK_SHIFT_MASK)
         {
	   delete this;	  
	   return TRUE;

         }
         break;
         
      default:
         break;
      }
      break;
     
      
   default:
      break;
   }
        
   return FALSE;
}

string GUINetTerminal::find_unique_name(const string &_name, NetTermType _type) {

  //automatic creation of an unique name for net terminals
  //could be better, but it works...
  //Dominic Letourneau Feb 1 2002.
  vector<string> my_terms = terminal->getNode()->getNetwork()->getTerminals(_type);
  int duplicate_count = 0;
 
  for (unsigned int i = 0; i < my_terms.size(); i++) {

    bool found = false;

    if (my_terms[i].size() >= _name.size()) {
      found = true;
      for (unsigned int j = 0; j < _name.size(); j++) {
	if (my_terms[i][j] != _name[j]) {
	  found = false;
	  break;
	}
      } 
    }
    if (found) {
      duplicate_count++;
    } 
  }

  if (duplicate_count > 0) {
    char name_id[10];
    sprintf(&name_id[0],"_%i",duplicate_count);
    return string(_name + string(name_id));
  }
  else {
    return _name;
  }
}

void GUINetTerminal::setAbsPos(double x, double y) {
  gnome_canvas_item_set(item,"x",x,"y",y,NULL);
}
}//namespace FD


syntax highlighted by Code2HTML, v. 0.9.1