//
// Algorithm    : vcg_dfa
// Description  : VCG ASCII representation of a dfa
// Input        : a dfa, a C string (title), an output stream
// Output       : result is writen on the output stream
// Precondition : DFA must export an iterator on Q
//              : Alphabet class must have an ASCII representation (operator <<)
//              : bool Tag::final()

#ifndef ASTL_DFALGO_VCG
#define ASTL_DFALGO_VCG

#include <signal.h>         // kill
#include <iostream>       // ostream, cout
#include <fstream>        // ofstream
#ifndef WIN32
#include <unistd.h>         // fork
#endif // WIN32
#include <string>
// #include </usr/include/g++/std/bastring.cc>
#include <map>

template <class FA>
void vcg(FA &fa, const char * title = NULL, ostream &out = cout)
{
	_vcg(fa, fa, title, out);
}

template <class ForwardIterator>
void vcg(ForwardIterator first, ForwardIterator last, const char * title = NULL, ostream &out = cout)
{
  out << "graph: { title: \"";
  if (title != NULL) out << title;
  out << "\" " << endl \
       << "         display_edge_labels: yes" << endl \
       << "         layoutalgorithm: minbackward" << endl \
       << "         orientation: left_to_right" << endl \
       << "         splines: yes" << endl \
       << "         yspace: 20" << endl \
       << "         splinefactor: 1" << endl \
       << "         straight_phase: yes" << endl \
       << "         arrowmode: free" << endl;
	for(int number = 0; first != last; ++first, ++number)
		_vcg_many(*first, *first, out, number);
	out << "}" << endl;
}

template <class DFA>
void _vcg(DFA_base &, DFA &dfa, const char * title = NULL, ostream &out = cout)
{
  out << "graph: { title: \"";
  if (title != NULL) out << title;
  out << "\" " << endl \
       << "         display_edge_labels: yes" << endl \
       << "         layoutalgorithm: minbackward" << endl \
       << "         orientation: left_to_right" << endl \
       << "         splines: yes" << endl \
       << "         yspace: 20" << endl \
       << "         splinefactor: 1" << endl \
       << "         straight_phase: yes" << endl \
       << "         arrowmode: free" << endl;

  typename DFA::const_iterator q, Q_end = dfa.end();

  for(q = dfa.begin(); q != Q_end; ++q)
  {
    out << "node: { title:\"" << *q << "\" label:\"" \
    	<< *q << " " << dfa.tag(*q) << "\" " << "color: "; 

    if (dfa.final(*q) == true)
      if (dfa.initial() == *q)
	out << "orange";    // Initial and final state
      else
	out << "red";     // Final state
    else
      if (dfa.initial() == *q)
	out << "green";   // Initial state
      else
	out << "white";   // Others
    
    out << " shape: ellipse}" << endl;
    
    typename DFA::Edges edg = dfa.delta2(*q);
    typename DFA::Edges::const_iterator trans, edg_end = edg.end();
    
    for(trans = edg.begin(); trans != edg_end; ++trans)
      out << "edge: { sourcename:\"" << *q << "\" targetname:\""  \
	  << (*trans).second << "\" label:\"" \
	  << (*trans).first << "\"}" << endl;
  }    
  out << "}" << endl;
}

template <class DFA>
void _vcg_many(DFA_base &, DFA &dfa, ostream &out, int number)
{

  typename DFA::const_iterator q, Q_end = dfa.end();

  for(q = dfa.begin(); q != Q_end; ++q)
  {
    out << "node: { title:\"" << number << " " << *q << "\" label:\"" \
    	<< *q << " " << dfa.tag(*q) << "\" " << "color: "; 

    if (dfa.final(*q) == true)
      if (dfa.initial() == *q)
	out << "orange";    // Initial and final state
      else
	out << "red";     // Final state
    else
      if (dfa.initial() == *q)
	out << "green";   // Initial state
      else
	out << "white";   // Others
    
    out << " shape: ellipse}" << endl;
    
    typename DFA::Edges edg = dfa.delta2(*q);
    typename DFA::Edges::const_iterator trans, edg_end = edg.end();
    
    for(trans = edg.begin(); trans != edg_end; ++trans)
      out << "edge: { sourcename:\"" << number << " " << *q << "\" targetname:\""  \
	  << number << " " << (*trans).second << "\" label:\"" \
	  << (*trans).first << "\"}" << endl;
  }    
}

#ifndef WIN32
static map<string, pid_t> __xvcg;

template <class DFA>
void run_vcg_dfa(DFA &dfa, const char *file_name, const char *title = "")
{
  ofstream file;

  file.open(file_name, ios::out | ios::trunc);
  vcg_dfa(dfa, title, file);
  file.close();

  if (__xvcg.find(file_name) != __xvcg.end())  // is this xvcg running already ?
    kill(__xvcg[file_name], SIGUSR1);  // simply refresh the screen 
  else     // launch a new xvcg
  {
    __xvcg[file_name] = fork();
    if (__xvcg[file_name] == 0)     // child process ?
      execlp("xvcg", "xvcg", "-silent", file_name, NULL);
  }
  char c;
  cin >> c;
}
#endif // WIN32

#endif








