/*   -*- coding: utf-8 -*-  */
#include <stdio.h>
#include "SxmlNode.h"
#include "TeiHandler.h"
#include "SxPath.h"
#include "StrDict.h"
#include <getopt.h>
#include <stdlib.h>

SxPathResult *authorPathOld;
SxPathResult *authorPath;
SxPathResult *datePath;
StrDict      *persDict;
StrDict      *persWikiDict;
StrDict      *persServerDict;
StrDict      *persJournalDict;

StrDict *orgDict;
char    *dateDoc;
char    *issnDoc;
int      traceMode;

Buffer *bufName;

SxmlNode *TeiTestDate(SxmlNode *nTest, char *dateInfo)
{
  char *toAtt;
  char *fromAtt;
  if (!dateInfo) return NULL;
  fromAtt=SxmlGetAttribute(nTest, "from");
  toAtt=SxmlGetAttribute(nTest, "to");
  if ((fromAtt)
      && (strcmp(dateInfo, fromAtt)<0)) return NULL;
  if ((toAtt)
      && (strcmp(dateInfo, toAtt)>0)) return NULL;
  return nTest;
}

SxmlNode *TeiCreateMergeAffiliation(SxmlNode *inputAffiliationNode, SxmlNode *targetNode)
{
  char *inputLevel;
  SxmlNode *dictCountryNode;
  /*  SxmlNode *inputCountryNode;
      char *inputCountry;             */
  char *dictCountry;

  inputLevel=SxmlGetAttribute(inputAffiliationNode, "wicri:level");
  if (!inputLevel) inputLevel="0";

  if ((dictCountryNode=SxmlGetFirstChildByTagName(targetNode,"country")))
    dictCountry=SxmlLeafText(dictCountryNode);
  else dictCountry=NULL;
  if(inputLevel[0]=='0')
    {
      SxmlAppendChild(inputAffiliationNode, SxmlClone(dictCountryNode));
    }
  return inputAffiliationNode;
}

SxmlNode *proceedInputAffiliation(SxmlNode *inputAffiliationNode, SxmlNode* dictAuthorNode)
{
  SxmlNode *targetAffiliation;
  char *inputLevel;
  SxmlNode *targetNode;

  inputLevel=SxmlGetAttribute(inputAffiliationNode, "wicri:level");
  if (!inputLevel) inputLevel="0";
  targetAffiliation=SxmlGetFirstChildByTagName(dictAuthorNode, "affiliation");
  if (!targetAffiliation)
    {
      if ((targetNode=SxmlGetFirstChildByTagName(dictAuthorNode, "org")))
	return TeiCreateMergeAffiliation(inputAffiliationNode, targetNode);
      else return NULL;
    }
  while (targetAffiliation)
    {
      SxmlNode *dictCountryNode;
      SxmlNode *inputCountryNode;
      char *inputCountry;
      char *dictCountry;
      if (traceMode>2)
	{
	  SxmlPrint (targetAffiliation);
	  putchar ('\n');
	}
      if (TeiTestDate(targetAffiliation, dateDoc))
	{
	  SxmlNode *orgNode;
	  char *orgName;
	  orgNode=SxmlGetFirstChildByTagName( targetAffiliation, "orgName");
	  if (orgNode) 
	    {
	      char *targetNodeStr;
	      orgName=SxmlLeafText(orgNode);
	      if (traceMode>1)
		{
		  printf("%s\n",  orgName);
		}
	      targetNodeStr=StrDictSearch(orgDict, orgName);
	      if (targetNodeStr)
		{
		  SxmlNode *dictPlaceName;
		  SxmlNode *dictOrgName;
		  if (traceMode>1)
		    {
		      printf("%s\n",  targetNodeStr);
		    }
		  targetNode=SxmlFromString(targetNodeStr);

		  if ((dictCountryNode=SxmlGetFirstChildByTagName(targetNode,"country")))
		    dictCountry=SxmlLeafText(dictCountryNode);
		  else dictCountry=NULL;
		  if(inputLevel[0]=='0')
		    {
		      SxmlAppendChild(inputAffiliationNode, SxmlClone(dictCountryNode));
		    }
		  if(inputLevel[0]=='1')
		    {
		      if ((inputCountryNode=SxmlGetFirstChildByTagName(inputAffiliationNode,"country")))
			inputCountry=SxmlLeafText(inputCountryNode);
		      else inputCountry=NULL;
		      if (strcmp(inputCountry, dictCountry)!=0)
			{
			  targetAffiliation=SxmlGetNextSiblingByTagName(targetAffiliation, "affiliation");
			  continue;
			}
		    }
		  dictPlaceName=SxmlGetFirstChildByTagName(targetNode,"placeName");
		  SxmlAppendChild(inputAffiliationNode, SxmlClone(dictPlaceName));
		  if (traceMode>2)
		    {
		      SxmlPrint (inputAffiliationNode);
		      putchar ('\n');
		    }
		  dictOrgName=SxmlGetFirstChildByTagName(targetNode,"orgName");
		  while(dictOrgName)
		    {
		      SxmlAppendChild(inputAffiliationNode, SxmlClone(dictOrgName));
		      dictOrgName=SxmlGetNextSiblingByTagName(dictOrgName,"orgName");
		    }
		  return inputAffiliationNode;
		}
	    }
	}
      targetAffiliation=SxmlGetNextSiblingByTagName(targetAffiliation, "affiliation");
    }
  return NULL;
}

SxmlNode *proceedAuthorInDict(SxmlNode *authorNode, SxmlNode *nameNode, char *authorName, StrDict *pDict)
{
  char *strAuthorRecord;
  SxmlNode *authorRecord;
  SxmlNode *authorNameNodeInRecord;
  SxmlNode *affiliationNode;
  SxmlNode *res;

  strAuthorRecord=StrDictSearch(pDict, authorName);
  if (!(strAuthorRecord))return NULL;
  authorRecord=SxmlFromString(strAuthorRecord);
  res=authorRecord;
  if (traceMode>2)
    {
      SxmlPrint(authorRecord);
      putchar ('\n');
    }
  authorNameNodeInRecord=SxmlGetFirstChildByTagName(authorRecord, "name");
  if (authorNameNodeInRecord)
    {
      char *authorNameInRecord;
      authorNameInRecord=SxmlLeafText(authorNameNodeInRecord);
      if (strcmp(authorNameInRecord, authorName)!=0)
	{
	  SxmlLeafSetText(nameNode, authorNameInRecord);
	}
    }
  affiliationNode=SxmlGetFirstChildByTagName(authorNode, "affiliation");
  if (!affiliationNode)
    {
      SxmlAppendChild(authorNode, affiliationNode=SxmlElementCreate("affiliation"));
    }
  if (traceMode>2)
    {
      SxmlPrint(affiliationNode);
      putchar ('\n');
    }
  while (affiliationNode)
    {
      proceedInputAffiliation(affiliationNode, authorRecord);
      affiliationNode=SxmlGetNextSiblingByTagName(affiliationNode, "affiliation");
    }
  return res;
}

SxmlNode *proceedAuthor(SxmlNode *authorNode)
{
  SxmlNode *nameNode;
  char *authorName;
  SxmlNode *res;

  nameNode=SxmlGetFirstChildByTagName(authorNode, "name");
  if (!nameNode)return NULL;
  authorName=SxmlLeafText(nameNode);
  if (traceMode>2)
    {
      printf("= author = %s\n", authorName);
    }
  res=NULL;
  if (persServerDict)
    {
      res=proceedAuthorInDict(authorNode, nameNode, authorName, persServerDict);
    }
  if ((!res) && (persWikiDict))
    {
      res=proceedAuthorInDict(authorNode, nameNode, authorName, persWikiDict);
    }
  if(!res)
    {
      res=proceedAuthorInDict(authorNode, nameNode, authorName, persDict);
    }
  if((!res)&&persJournalDict&&issnDoc)
    {
      BufferStrcpy(bufName, issnDoc);
      BufferStrcat(bufName, ":");
      BufferStrcat(bufName, authorName);
      if (traceMode >2)
	{
	  printf("= author key = %s\n", BufferString(bufName));
	}
      res=proceedAuthorInDict(authorNode, nameNode, BufferString(bufName), persJournalDict);
    }
  return res;
  /*
                  To be improved */
}     

    int getopt();
    extern char *optarg;

int main (int argc, char **argv)
{
  SxmlNode *docInput;
  int cOption;
  traceMode=0;

  persDict=NULL;
  persWikiDict=NULL;
  persJournalDict=NULL;
  bufName=NewBuffer();
  while((cOption=getopt(argc,argv,"j:o:p:s:T:w:"))!=EOF)
    {switch (cOption)
        {
	case 'j' :
	  persJournalDict=StrDictFromFile(optarg);
	  break;
	case 'o' :
	  orgDict=StrDictFromFile(optarg);
	  break;
	case 'p' :
	  persDict=StrDictFromFile(optarg);
	  break;
	case 's' :
	  persServerDict=StrDictFromFile(optarg);
	  break;
	case 'w' :
	  if (!persWikiDict) persWikiDict=StrDictFromFile(optarg);
	  else StrDictAddFromFile(persWikiDict, optarg);
	  break;
	case 'T':
	  traceMode=atoi(optarg);
	  break;
	}
    }

  authorPath=SxPathSetCompile("TEI/teiHeader/fileDesc/sourceDesc/biblStruct/analytic/author");
  authorPathOld=SxPathSetCompile("TEI/teiHeader/fileDesc/titleStmt/author");
  datePath=SxPathFirstCompile("TEI/teiHeader/fileDesc/publicationStmt/date");
  /*  while ((docInput=SxmlInputNextDocumentElement())) */
  while(TeiInputNextRecord())
    {
      SxmlNode *dateNode;
      SxmlNode *listAuthors;

      if (traceMode>2)
	{
	  printf("=========== %s ===========\n", SxmlInputRecordKey);
	}

      docInput=SxmlParent (Tei_root);
      if (persJournalDict)issnDoc=TeiHandlerGetIssn();
      dateNode=SxPathFirstResultNode(datePath, docInput);

      if (dateNode)dateDoc=SxmlLeafText(dateNode);
      else dateDoc=NULL;

      if (traceMode>2)
	{
	  printf("= date = %s\n", dateDoc);
	}

      if((listAuthors=SxPathSetResultListCreate(authorPath, docInput)))
	{
	  SxmlNode *author;
	  
	  while((author=SxmlNodeListNextNode(listAuthors)))
	     {
	       proceedAuthor(author);       
	     } 
	}
      if((listAuthors=SxPathSetResultListCreate(authorPathOld, docInput)))
	{
	  SxmlNode *author;
	  
	  while((author=SxmlNodeListNextNode(listAuthors)))
	     {
	       proceedAuthor(author);       
	     } 
	}
      if (traceMode <2 ) SxmlPrint (SxmlInputRecord);
    }
  exit(EXIT_SUCCESS);
}
