/*   -*- coding: utf-8 -*-  */

/*
           TeiBuildAffiliationTree

 */

#include <stdio.h>     /* for printf */
#include <stdlib.h>    /* for exit */
#include <getopt.h>
#include "SxPath.h"
#include "Buffer.h"
#include "TeiHandler.h"

SxmlNode *docInput;
SxmlNode *teiRoot;

SxmlNode *listCountry;
SxmlNode *listRegion;
SxmlNode *listCity;
SxmlNode *listOrg;

SxPathResult *pathTeiAnalytic;

void insertNameInList(SxmlNode *list, SxmlNode *nameNode)
{
  char *keyInsert;
  SxmlNode *listNode;
  keyInsert=SxmlGetAttribute(nameNode,"sort");
  if (!keyInsert)keyInsert=SxmlLeafText(nameNode);
  listNode=SxmlFirstChild(list);
  while (listNode)
    {
      char *keyList;
      if (!(SxmlNodeHasName(listNode, "name")))
	{
	  listNode=SxmlNextSibling(listNode);
	  continue;
	}
      keyList=SxmlGetAttribute(listNode,"sort");
      if (!keyList)keyList=SxmlLeafText(listNode);
      if (strcmp(keyInsert, keyList)<0)
	{
	  SxmlInsertBefore(listNode, SxmlClone(nameNode));
	  return;
	}
      listNode=SxmlNextSibling(listNode);
    }
  SxmlAppendChild(list, SxmlClone(nameNode));
}

void insertNoCountry(SxmlNode *tree, SxmlNode *nameNode)
{
  SxmlNode *noCountryNode;
  noCountryNode=SxmlGetFirstChildByTagName(tree,"noCountry");
  if (!noCountryNode)
    {
      SxmlAddFirstChild(tree, noCountryNode=SxmlElementCreate("noCountry"));
      SxmlAppendChild (noCountryNode, SxmlClone(nameNode));
      return;
    }
  insertNameInList(noCountryNode, nameNode);
}

SxmlNode *insertNoRegion(SxmlNode *country,  SxmlNode *nameNode)
{
  SxmlNode *noRegionNode;
  noRegionNode=SxmlGetFirstChildByTagName(country,"noRegion");
  if (!noRegionNode)
    {
      SxmlAddFirstChild(country, noRegionNode=SxmlElementCreate("noRegion"));
      SxmlAppendChild (noRegionNode, SxmlClone(nameNode));
      return noRegionNode;
    }
  insertNameInList(noRegionNode, nameNode);
  return noRegionNode;
}

SxmlNode *buildCountry(char *countryName, SxmlNode *authorNode, SxmlNode *affiliation, SxmlNode *nameNode)
{
  SxmlNode *countryTree;
  SxmlNode *placeName;
  SxmlNode *noRegionNode;
  placeName=SxmlGetFirstChildByTagName(affiliation, "placeName");
  countryTree=SxmlElementCreate("country");
  SxmlSetAttribute(countryTree, "name", countryName);
  if(placeName)
    {
      SxmlNode *regionTei;

      regionTei=SxmlGetFirstChildByTagName(placeName, "region");
      if(regionTei)
	{
	  SxmlNode *regionNode;
	  regionNode=SxmlElementCreate("region");
	  SxmlSetAttribute(regionNode, "name", SxmlLeafText(regionTei));
	  SxmlAppendChild(regionNode, SxmlClone(nameNode));
	  SxmlAppendChild(countryTree, regionNode);
	  return countryTree;
	}
    }
  noRegionNode=insertNoRegion(countryTree,  nameNode);
    /* SxmlAppendChild(countryTree, SxmlClone(nameNode)); */
  return countryTree;
}

void  insertCountry(SxmlNode *tree, SxmlNode *authorNode, SxmlNode *affiliation, char *authorCountry, SxmlNode *nameNode)
{
  SxmlNode *countryTree;
  char *countryTreeName;
  countryTree=SxmlGetFirstChildTagAtt(tree, "country", "name", authorCountry);
  if (!countryTree)
    {
      countryTree=buildCountry(authorCountry, authorNode, affiliation, nameNode);
      SxmlAppendChild(tree, countryTree);
      return;
    }
  while(countryTree)
    {
      countryTreeName=SxmlGetAttribute(countryTree, "name");
      if (strcmp(countryTreeName, authorCountry)==0)
	{
	  insertNameInList(countryTree, nameNode);
	  return;
	}
      if (strcmp(countryTreeName, authorCountry)>0)
	{
	  countryTree=buildCountry(authorCountry, authorNode, affiliation, nameNode);
	  SxmlAddFirstChild(countryTree, nameNode);
	  return;
	}
      countryTree=SxmlGetNextSiblingTagAtt(countryTree, "country", "name", authorCountry);
    }
  countryTree=buildCountry(authorCountry, authorNode, affiliation, nameNode);
  SxmlAppendChild(tree, countryTree);
  return;
}

void insertNodeInList (SxmlNode *list, SxmlNode *item)
{
  SxmlNode *itemInList;
  char *itemName;
  itemInList=SxmlFirstChild(list);
  if (!itemInList)
    {
      SxmlAppendChild(list, item);
      return;
    }
  itemName=SxmlLeafText(item);
  if (!itemName)
    {
      SxmlFree(item);
      return;	
    }
  while (itemInList)
    {
      char *curName;
      int testName;
      curName=SxmlLeafText(itemInList);
      if (!curName)
	{
	  SxmlFree(item);
	  return;
	}
      testName=strcmp(curName, itemName);
      if (testName==0) 
	{
	  SxmlFree(item);
	  return;
	}
      if (testName > 0) 
	{
	  SxmlInsertBefore(itemInList, item);
	  return;
	}
      itemInList=SxmlNextSibling(itemInList);
    }
  SxmlAppendChild(list, item);
}

void listAuthorItems(SxmlNode *list, SxmlNode *authorNode)
{
  SxmlNode *affiliation;
  affiliation=SxmlGetFirstChildByTagName(authorNode, "affiliation");
  while (affiliation)
    {
      SxmlNode *affItem;

      SxmlReset(affiliation);
      while((affItem=SxmlNextNode(affiliation)))
	{
	  if (SxmlNodeHasName(affItem,"country"))
	    {
	      insertNodeInList(listCountry, SxmlLeafCreate("li", SxmlLeafText(affItem)));
	    }
	  else if (SxmlNodeHasName(affItem,"orgName"))
	    {
	      insertNodeInList(listOrg, SxmlLeafCreate("li", SxmlLeafText(affItem)));
	    }
	  else if (SxmlNodeHasName(affItem,"placeName"))
	    {
	      SxmlNode *placeItem;
	      SxmlReset(affItem);
	      while ((placeItem=SxmlNextNode(affItem)))
		{
		  if (SxmlNodeHasName(placeItem,"region"))
		    {
		      insertNodeInList(listRegion, SxmlLeafCreate("li", SxmlLeafText(placeItem)));
		    }
		  else if (SxmlNodeHasName(placeItem,"settlement"))
		    {
		      insertNodeInList(listCity, SxmlLeafCreate("li", SxmlLeafText(placeItem)));
		    } 
		}
	    }
	}
      affiliation=SxmlGetNextSiblingByTagName(affiliation, "affiliation");
    }
}

void insertAuthor(SxmlNode *tree, SxmlNode *authorNode)
{
  SxmlNode *authorCountryNode;
  SxmlNode *affiliation;
  SxmlNode *nameNode;
  char *name;
  int hasCountry;

  hasCountry=0;
  nameNode=SxmlGetFirstChildByTagName(authorNode,"name");
  if (!nameNode) return;
  name=SxmlLeafText(nameNode);
  affiliation=SxmlGetFirstChildByTagName(authorNode, "affiliation");
  if(!affiliation)
    {
      insertNoCountry(tree, nameNode);
      return;
    }
  while (affiliation)
    {
      authorCountryNode=SxmlGetFirstChildByTagName(affiliation, "country");
      if (authorCountryNode) 
	{
	  hasCountry=1;
	  insertCountry(tree, authorNode, affiliation, SxmlLeafText(authorCountryNode), nameNode);
	}
      affiliation=SxmlGetNextSiblingByTagName(affiliation, "affiliation");
    }
  if (hasCountry==0) insertNoCountry(tree, nameNode);
  return;
}

int main()
{
  pathTeiAnalytic=SxPathFirstCompile("teiHeader/fileDesc/sourceDesc/biblStruct/analytic");

  while ((docInput=SxmlInputNextDocumentElement()))
    {
      if(SxmlNodeHasName(docInput,"record"))
	{
	  SxmlNode *treeAffiliation;
	  SxmlNode *analytic;
	  SxmlNode *listAffiliation;
	  SxmlNode *affiliation;

	  teiRoot=SxmlGetFirstChildByTagName(docInput,"TEI");
	  
	  analytic=SxPathFirstResultNode(pathTeiAnalytic, teiRoot);
	  if (analytic)
	    {
	      SxmlNode *authorNode;
	      affiliation=SxmlElementCreate("affiliations");
	      listAffiliation=SxmlElementCreate("list");
	      treeAffiliation=SxmlElementCreate("tree");
	      SxmlAppendChild(docInput, affiliation);
	      SxmlAppendChild(affiliation, listAffiliation);
	      SxmlAppendChild(listAffiliation, listCountry=SxmlElementCreate("country"));
	      SxmlAppendChild(listAffiliation, listRegion=SxmlElementCreate("region"));
	      SxmlAppendChild(listAffiliation, listCity=SxmlElementCreate("settlement"));
	      SxmlAppendChild(listAffiliation, listOrg=SxmlElementCreate("orgName"));
	      SxmlAppendChild(affiliation, treeAffiliation);
	      authorNode=SxmlGetFirstChildByTagName(analytic, "author");
	      while(authorNode)
		{
		  insertAuthor(treeAffiliation, authorNode);
		  listAuthorItems(listAffiliation, authorNode);
		  authorNode=SxmlGetNextSiblingByTagName(authorNode, "author");
		}
	      if (!SxmlFirstChild(listOrg))SxmlFree(listOrg);
	      if (!SxmlFirstChild(listCity))SxmlFree(listCity);
	      if (!SxmlFirstChild(listRegion))SxmlFree(listRegion);
	      if (!SxmlFirstChild(listCountry))SxmlFree(listCountry);
	    }
	  
	}
      SxmlPrint(SxmlInputRecord);
    }

  exit (EXIT_SUCCESS);
}
