#include "global.hh"
#include "sgraph.hh"
#include "mgraph.hh"
#include "grammar.hh"
#include "const.hh"
#include <stdio.h>


int SGraph::add_base_snode(MNode* mn)
{
  int nodeind=n;
  SNode &node=nodes[n];

  node.clear();

  node.mnode=mn;

  for(vector<MNode*>::iterator pm=node.mnode->pred.begin(); pm!=node.mnode->pred.end(); ++pm)
    for(vector<int>::iterator ps=(*pm)->snodes.begin(); ps!=(*pm)->snodes.end(); ++ps)
      if(nodes[*ps].in_LH)
      {
        node.LV.set(*ps);
        if(nodes[*ps].saturated()) node.LV |= nodes[*ps].LH;
      }

  mn->snodes.push_back(nodeind);
  ++n;

  node.in_LH=true;

  return nodeind;
}


void SGraph::update_left(int headind, int depind)
{
  SNode &head=nodes[headind], &dep=nodes[depind];

  if(dep.saturated()) head.LV |= dep.LV, head.LD |= dep.LD;
}


void SGraph::update_right(int headind, int depind)
{
  SNode &head=nodes[headind], &dep=nodes[depind];

  dep.LH.set(headind);
  if(head.saturated())
    dep.LH |= head.LH;
}


int SGraph::clone(int ancind, NodeProp newprop)
{
  int newind = n++;
  SNode &newnode=nodes[newind];
  SNode &ancnode = nodes[ancind];

  newnode.clear();
  newnode.prop=newprop;
  newnode.mnode=ancnode.mnode;
  newnode.mnode->snodes.push_back(newind);
  return newind;
}


//-------------------------------------------------------------------------
//-------------------------------------------------------------------------


int SGraph::print_node(FILE* f, int n, unsigned int info)
{
  char buf[1000];
  sprint_node(buf,n,info);
  fputs(buf,f);
}

int SGraph::sprint_node(char* buf, int nodeind, unsigned int info)
{
  char* buf0=buf;
  char descr[256];
  char nodeinfo[16];

  SNode &node=nodes[nodeind];

  buf+=sprintf(buf," dgp:%d",nodeind);
  buf+=sprintf(buf, saturated(nodeind) ? ";s" : ";u");

  bool cont=false;
  if (info&HEADS)
  {
    buf+=sprintf(buf,";");
    for(vector<Arc>::iterator h=node.heads.begin(); h!=node.heads.end(); ++h)
    {
      if(cont) buf+=sprintf(buf,","); else cont=true;
      buf+=sprintf(buf,"++%s-%d/%d",h->role.str(),h->dst,h->anc);
    }
  }
  
  if (info&DEPS)
  {
    buf+=sprintf(buf,";");
    for(vector<Arc>::iterator d=node.deps.begin(); d!=node.deps.end(); ++d)
    {
      //      if(! nodes[d->dst].saturated()) continue; // NIE DRUKUJ NIENASYCONYCH PODRZEDNIKOW
      if(cont) buf+=sprintf(buf,","); else cont=true;
      buf+=sprintf(buf,"--%s-%d/%d",d->role.str(),d->dst,d->anc);
    }
  }
  
  if (info&SETS)
  {
    int ord=0;
    buf+=sprintf(buf,";{");
    for(vector<MNode*>::iterator pm=node.mnode->pred.begin(); pm!=node.mnode->pred.end(); ++pm)
      for(vector<int>::iterator ps=(*pm)->snodes.begin(); ps!=(*pm)->snodes.end(); ++ps)
        buf+=sprintf(buf, ord++ ? ",%d" : "%d", *ps);
    buf+=sprintf(buf,"};{");
    ord=0;for(int j=0; j<=n; ++j) if(node.LV[j]) buf+=sprintf(buf, ord++ ? ",%d" : "%d", j);
    buf+=sprintf(buf,"};{");
    ord=0;for(int j=0; j<=n; ++j) if(node.LH[j]) buf+=sprintf(buf, ord++ ? ",%d" : "%d", j);
    buf+=sprintf(buf,"};{");
    ord=0;for(int j=0; j<=n; ++j) if(node.LD[j]) buf+=sprintf(buf, ord++ ? ",%d" : "%d", j);
    buf+=sprintf(buf,"}");
  }

  if (info&CONSTRAINTS)//  buf+=sprint_node_constraints(buf,n);
  {
    buf+=sprintf(buf,";");
    int cont=0;
    for(Role i=1; i<=Role::count(); ++i)
      if(node.prop.forbidden[i]) buf+=sprintf(buf,"%s!%s",(cont++)?",":"",i.str());
    for(Role i=1; i<=Role::count(); ++i)
      if(node.prop.required[i]) buf+=sprintf(buf,"%s&%s",(cont++)?",":"",i.str());
  }
  
//   buf+=sprintf(buf,"\n");
  
  return buf-buf0;
}


int SGraph::sprint_node_debug(char* buf, const char* pref, int n)
{
  char *buf0 = buf;
  buf+=sprintf(buf,"#%s",pref);
  buf+=sprint_node(buf,n,HEADS|DEPS|SETS|CONSTRAINTS);
  buf+=sprintf(buf,"\n");
  return buf-buf0;
}

int SGraph::print_node_debug(FILE* f, const char* pref, int n)
{
  char buf[1000];
  sprint_node_debug(buf,pref,n);
  fputs(buf,f);
}

void SGraph::print_arc(FILE* f, int left, int right, Role role, int dir) // 0 - left, 1 - right
{
  fprintf(f,"#   %s:%s.%02d %s %s.%02d\n",
          role.str(),nodes[left].mnode->type,left,
          dir ? "-->" : "<--",
          nodes[right].mnode->type,right);
}
