/*   -*- coding: utf-8 -*-  */
/***********************************************************************
*
*               Module   : MediaWiki
*               Fichier  : MediaWikiTableTransformCol.c
*               Auteur   : Ducloy
*               Date     : Février 2013
*
************************************************************************
*
* Copyleft 2013 Jacques Ducloy 
* 
************************************************************************/
#include <stdio.h>     /* for printf */
#include <stdlib.h>    /* for exit */
#include <getopt.h>

#include "SxmlNode.h"
#include "RegExp.h"
#include "MediaWiki.h"

SxmlNode *inputRow;

int getopt();
extern char *optarg;
char *unLineSet;
char *linkPageSet;
char *listTermSet;
char *listLinkSet;
char *listElemSet;
char *listCutSet;
char *listNewTagSet;
SxmlNode *listNewTag;
char *nameNodeCol;
char *nameNodeCol2;
char  inputListSeparator;
Buffer *bufTerm;
Buffer *bufPrint;
char *implicitElementName;
char *keyOpt;
char *keyOptStrongLink;
char *valueOpt;
char *valueLinkOpt;
char *valueWikiLinkOpt;
char *filterKey;

MediaWikiParser *wikiParser;

char *mediaWikiTableAppendChildLinkPage(SxmlNode *colNode, char *str)
{
  SxmlNode *newNode;
  if (strncmp(str, "[[", 2)==0)
    {
      char *posBar;
      char *posRightBrack;
      char *strL1;
      if ((posRightBrack=strchr(str, ']')))
	{
	  strL1=str+2;
	  while (strL1[0]==' ')strL1++;
	  SxmlAppendChild(colNode, newNode=SxmlElementCreate("p"));
	  if ((posBar=strchr(str, '|')) &&(posBar < posRightBrack))
	    {
	      SxmlAppendChild(newNode, SxmlLeafCreateFromSubstr("k", strL1, posBar-strL1));
	      SxmlAppendChild(newNode, SxmlLeafCreateFromSubstr("t", posBar+1, posRightBrack-posBar-1));
	    }
	  else
	    {
	      SxmlAppendChild(newNode, SxmlLeafCreateFromSubstr("k", strL1, posRightBrack-strL1));
	      SxmlAppendChild(newNode, SxmlLeafCreateFromSubstr("t", strL1, posRightBrack-strL1));
	    }
	  return (posRightBrack+2);
	}
    }
  return NULL;
}


SxmlNode *mediaWikiTableSetAtt(SxmlNode *elem, char *str)
{
  char *posEqual;
  char *posSpace;
  char *posAt;
  char *tag;
  char *endTag;
  char *value;
  static Buffer *bufTerm2=NULL;
  static Buffer *bufTerm3=NULL;

  if (!bufTerm2)bufTerm2=NewBuffer();
  if (!bufTerm3)bufTerm3=NewBuffer();
  tag=str;
  while (tag[0]==' ')tag++;
  posEqual=strchr(tag,'=');
  if (!posEqual)return NULL;
  posSpace=strchr(tag,' ');
  posAt=strchr(tag,'@');
  if (posSpace&&(posSpace<posEqual))endTag=posSpace;
  else endTag=posEqual;
  BufferStrncpy(bufTerm2, tag, endTag-tag);
  value=posEqual+1;
  while (value[0]==' ')value++;
  if (value[0]=='\"')
    {
      char *posDquot;
      posDquot=strchr(value+1,'\"');
      if (!posDquot)
	{
	}
      BufferStrncpy(bufTerm3, value+1, posDquot-value-1);
      SxmlSetAttribute(elem, BufferString(bufTerm2), BufferString(bufTerm3));
    }
  else
    {
      if (posAt)
	{
	  if (posSpace&&(posSpace<posAt))BufferStrncpy(bufTerm3, value, posSpace-value);
	  else BufferStrncpy(bufTerm3, value, posAt-value);
	  SxmlSetAttribute(elem, BufferString(bufTerm2), BufferString(bufTerm3));
	}
      else
	{
	  if (posSpace)  
	    {
	      BufferStrncpy(bufTerm3, value, posSpace-value);
	      SxmlSetAttribute(elem, BufferString(bufTerm2), BufferString(bufTerm3));
	    }
	  else SxmlSetAttribute(elem, BufferString(bufTerm2), value);
	}
    }

  if (posAt) 
    {
      return mediaWikiTableSetAtt(elem, posAt+1);
    }
  return elem;
}

char *findSemiColonInXml(char *str)
{
  char *posSemiColon;
  char *posAmpersand;
  if (!str)return NULL;
  posSemiColon=strchr(str,';');
  if (!posSemiColon) return NULL;
  posAmpersand=strchr(str,'&');
  if (!posAmpersand) return posSemiColon;
  if (posSemiColon < posAmpersand) return posSemiColon;
  return findSemiColonInXml(posSemiColon+1);
}

SxmlNode *mediaWikiTableAppendElem(SxmlNode *colNode, char *str)
{
  char *str1;
  char *posSep;
  char *posSemiColon;
  char *posAt;
  char *posSpace;
  char *endTerm;
  char *value;
  SxmlNode *elem;
  char *posEnd;
  static Buffer *bufTerm2=NULL;
  static Buffer *bufTerm3=NULL;
  int lenCopy;

  if (!str)return NULL;
  if (strlen(str)<1) return NULL;
  if (!bufTerm2)bufTerm2=NewBuffer();
  if (!bufTerm3)bufTerm3=NewBuffer();
  str1=str;
  while (*str1==' ')str1++;
  if (!str1)return NULL;
  /* if (posSep=strchr(str1,inputListSeparator))lenCopy=posSep-str1-1; */
  if (inputListSeparator==';')
    {
      posSep=findSemiColonInXml(str1);
    }
  else
    {
      posSep=strchr(str1,inputListSeparator);
    }
  /*  if ((posSep=strchr(str1,inputListSeparator)))lenCopy=posSep-str1; */
  if (posSep)lenCopy=posSep-str1;
  else lenCopy=strlen(str1);
  while (lenCopy>0&&(str[lenCopy-1]==' '))lenCopy--;
  BufferStrncpy(bufTerm, str1, lenCopy);
  posSemiColon=strrchr(BufferString(bufTerm),':');
  posAt=strchr(BufferString(bufTerm),'@');
  if (!posSemiColon)
    {
      SxmlAppendChild(colNode,elem=SxmlElementCreate(implicitElementName));
      if (posAt) mediaWikiTableSetAtt(elem,posAt+1);
      if (posSep)mediaWikiTableAppendElem(colNode, posSep+1);
      return colNode;
    }
  posSpace=strchr(BufferString(bufTerm),' ');
  if (posAt)
    {
      if (posSpace&&(posAt>posSpace)) endTerm=posSpace;
      else endTerm=posAt;
    }
  else
    {
      if (posSpace&&(posSemiColon>posSpace)) endTerm=posSpace;
      else endTerm=posSemiColon;
    }
  BufferStrncpy(bufTerm2, BufferString(bufTerm), endTerm-BufferString(bufTerm));
  value=posSemiColon+1;
  while (value[0]==' ') value++;
  posEnd=strchr(value,']');
  if ((strncmp(value,"[[",2)==0)&&posEnd)
    {
      char *beginLink;
      beginLink=value+2;
      while (beginLink[0]==' ') beginLink++;
      BufferStrncpy(bufTerm3, beginLink, posEnd-beginLink);
      SxmlAppendChild(colNode, elem=SxmlLeafCreate(BufferString(bufTerm2), BufferString(bufTerm3)));
    }      
  else SxmlAppendChild(colNode, elem=SxmlLeafCreate(BufferString(bufTerm2), value));
  if (posAt&&(posAt<posSemiColon))
    {
      BufferStrncpy(bufTerm2, posAt+1, posSemiColon-posAt-1);
      mediaWikiTableSetAtt(elem, BufferString(bufTerm2));
    }
  if (posSep)mediaWikiTableAppendElem(colNode, posSep+1);
  return colNode;
}

char *mediaWikiTableAppendListLink(SxmlNode *colNode, char *str)
{
  char *posBr;
  char *posBr2;
  char *posSep;
  posBr=strchr(str,'[');
  if (!posBr)return NULL;
  posBr2=mediaWikiTableAppendChildLinkPage(colNode, posBr);
  if (!posBr2)return NULL;
  if ((posSep=strchr(posBr2,inputListSeparator))) mediaWikiTableAppendListLink(colNode, posSep) ;
  return posSep;
}

char *proceedFilterKey (char *str)
{
  /*  static SxmlNode *nodeAuthor=NULL; */
  static RegExp *reFilter=NULL;
  if (strncmp(filterKey, "regexp:", 7)==0)
    {
      if (!reFilter) reFilter=RegExpCreate(filterKey+7);
      return RegExpExtract(reFilter, str);
    }
  return NULL;
}

int main (int argc, char **argv) {
  int cOption;

  unLineSet=NULL;
  linkPageSet=NULL;
  inputListSeparator=';';
  listTermSet=NULL;
  listElemSet=NULL;
  listLinkSet=NULL;
  listCutSet=NULL;
  listNewTagSet=NULL;
  unLineSet=NULL;
  keyOpt=NULL;
  keyOptStrongLink=NULL;
  valueOpt=NULL;
  valueLinkOpt=NULL;
  valueWikiLinkOpt=NULL;
  linkPageSet=NULL;
  filterKey=NULL;
  listNewTag=SxmlElementCreate("list");
  implicitElementName="i";
  bufTerm=NewBuffer();
  bufPrint=NewBuffer();
  wikiParser=NewMediaWikiParser();

  nameNodeCol=malloc(3);
  nameNodeCol2=malloc(3);
  strcpy(nameNodeCol,"c0");
  strcpy(nameNodeCol2,"c0");
  while((cOption=getopt(argc,argv,"c:e:f:k:K:u:s:t:E:n:N:T:l:L:p:w:v:V:W:"))!=EOF)
    {
      switch (cOption)
	{
	case 'c':
	  listCutSet=optarg;
	  break;
	case 'e':
	  implicitElementName=optarg;
	  break;
	case 'f':
	  filterKey=optarg;
	  break;
	case 'k':
	  keyOpt=optarg;
	  break;
	case 'K':
	  keyOptStrongLink=optarg;
	  break;
	case 's':
	  inputListSeparator=*optarg;
	  break;
	case 'u':
	case 't':
	  unLineSet=optarg;
	  break;
	case 'E':
	  listElemSet=optarg;
	  break;
	case 'n':
	  listNewTagSet=optarg;
	  break;
	case 'N':
	  SxmlAppendChild(listNewTag, SxmlLeafCreate("tag",optarg));
	  break;
	case 'T':
	  listTermSet=optarg;
	  break;
	case 'l':
	  linkPageSet=optarg;
	  break;
	case 'L':
	  listLinkSet=optarg;
	  break;
	case 'v':
	  valueOpt=optarg;
	  break;
	case 'V':
	  valueLinkOpt=optarg;
	  break;
	case 'W':
	  valueWikiLinkOpt=optarg;
	  break;
	}
    }
  while ((inputRow=SxmlInputNextDocumentElement()))
    {   
      int i;
      int col;
      SxmlNode *nodeToTransform;
      if (keyOpt)
	{
	  SxmlNode *child1;
	  SxmlNode *child2;
	  nameNodeCol[1]=keyOpt[0];
	  if(keyOpt[1])nameNodeCol2[1]=keyOpt[1];
	  if ((nodeToTransform=SxmlGetFirstChildByTagName(inputRow,nameNodeCol))
	      &&(child1=SxmlFirstChild(nodeToTransform)))
	    {
	      char *inputKey;
	      inputKey=SxmlLeafText(child1);
	      if (filterKey)
		{
		  char *outputKey;
		  outputKey=proceedFilterKey (inputKey);
		  if (!outputKey)continue;
		  printf("%s", outputKey);
		  free (outputKey);
		}
	      else printf("%s", inputKey);
	      if(keyOpt[1]
		 &&(nodeToTransform=SxmlGetFirstChildByTagName(inputRow,nameNodeCol2))
		 &&(child2=SxmlFirstChild(nodeToTransform)))
		{
		  printf(":%s", SxmlLeafText(child2));
		}
	      putchar('\t');
	    }
	  else continue;
	}
      if (keyOptStrongLink)
	{
	  SxmlNode *child1;

	  nameNodeCol[1]=keyOptStrongLink[0];
	  if ((nodeToTransform=SxmlGetFirstChildByTagName(inputRow,nameNodeCol))
	      &&(child1=SxmlFirstChild(nodeToTransform)))
	    {
	      char *str;
	      static Buffer *bLink=NULL;
	      char *posRightBrack;

	      if (!bLink)bLink=NewBuffer();

	      str=SxmlLeafText(child1);
	      if (strncmp(str, "[[", 2)!=0)continue;
	      if (strchr(str, '|')) continue;
	      posRightBrack=strchr(str, ']');
	      if (!posRightBrack) continue;
	      BufferStrncpy(bLink, str+2, posRightBrack-str-2);
	      printf("%s\t", BufferString(bLink));
	    }
	  else continue;
	}
      if (valueOpt)
	{
	  SxmlNode *child1;
	  nameNodeCol[1]=valueOpt[0];
	  nodeToTransform=SxmlGetFirstChildByTagName(inputRow,nameNodeCol);
	  if (!nodeToTransform)
	    {
	      printf ("\n");
	      continue;
	    }
	  if ((child1=SxmlFirstChild(nodeToTransform)))
	    {
	      printf("%s\n", SxmlLeafText(child1));
	    }
	  continue;
	}
      if (valueLinkOpt)
	{
	  SxmlNode *child1;
	  nameNodeCol[1]=valueLinkOpt[0];
	  nodeToTransform=SxmlGetFirstChildByTagName(inputRow,nameNodeCol);
	  if (!nodeToTransform)
	    {
	      printf ("\n");
	      continue;
	    }
	  if ((child1=SxmlFirstChild(nodeToTransform)))
	    {
	      char *str;
	      str=SxmlLeafText(child1);
	      if (!str)
		{
		  printf ("\n");
		  continue;
		}
	      if (strncmp(str, "[[", 2)==0)
		{
		  char *posBar;
		  char *posRightBrack;
		  char *strL1;
		  if ((posRightBrack=strchr(str, ']')))
		    {
		      strL1=str+2;
		      while (strL1[0]==' ')strL1++;
		      if ((posBar=strchr(str, '|')) &&(posBar < posRightBrack))
			{
			  BufferStrncpy(bufPrint,strL1, posBar-strL1);
			}
		      else
			{
			  BufferStrncpy(bufPrint,strL1, posRightBrack-strL1);
			}
		      printf ("%s\n", BufferString(bufPrint));
		    }
		}
	      else printf("%s\n", str);
	    }
	  continue;
	}
      if (valueWikiLinkOpt)
	{
	  SxmlNode *child1;
	  SxmlNode *child2;
	  nameNodeCol[1]=valueWikiLinkOpt[0];
	  nodeToTransform=SxmlGetFirstChildByTagName(inputRow,nameNodeCol);
	  if(!nodeToTransform)continue;
	  child1=SxmlFirstChild(nodeToTransform);
	  if (!SxmlIsLeaf(child1))continue;
	  if (SxmlNodeHasName(child1, "i"))
	    {
	      printf("%s\n", SxmlLeafText(child1));
	      continue;
	    }
	  if ((child2=SxmlNextSibling(child1)))
	    {
	      printf("[[%s", SxmlLeafText(child1));
	      printf("|%s]]\n", SxmlLeafText(child2));
	      continue;
	    }
	  else
	    {
	      printf("[[%s]]\n", SxmlLeafText(child1));
	      continue;
	    }
	}
      if (unLineSet)
	{
	  i=0;
	  while ((col=unLineSet[i++]))
	    {
	      SxmlNode *child1;
	      SxmlNode *child2;
	      nameNodeCol[1]=col;
	      if ((nodeToTransform=SxmlGetFirstChildByTagName(inputRow,nameNodeCol))
		  && (child1=SxmlFirstChild(nodeToTransform))
		  &&(child2=SxmlFirstChild(child1)))
		{
		  SxmlRemoveChild(child2);
		  SxmlReplaceChild(child1, child2);
		  SxmlFree(child1);
		} 
	    }
	}

      if (linkPageSet)
	{
	  i=0;
	  while ((col=linkPageSet[i++]))
	    {
	      SxmlNode *child1;
	      SxmlNode *child2;
	      nameNodeCol[1]=col;
	      if ((nodeToTransform=SxmlGetFirstChildByTagName(inputRow,nameNodeCol))
		  && (child1=SxmlFirstChild(nodeToTransform))
		  && (child2=SxmlFirstChild(child1)))
		{
		  char *strLinkPage;
		  strLinkPage=SxmlNodeValue(child2);
		  SxmlRemoveChild(child1);
		  mediaWikiTableAppendChildLinkPage(nodeToTransform, strLinkPage);
		  SxmlFree(child1);
		}
	    }
	}

      if (listTermSet)
	{
	  i=0;
	  while ((col=listTermSet[i++]))
	    {
	      nameNodeCol[1]=col;
	      if ((nodeToTransform=SxmlGetFirstChildByTagName(inputRow,nameNodeCol)))
		{
		  SxmlNode *newCol;
		  MediaWikiSetListTag(wikiParser,nameNodeCol);
		  newCol=MediaWikiSxmlFromListText(wikiParser, nodeToTransform);
		  /*
		  SxmlNode *lineNode;
		  newCol=SxmlElementCreate(nameNodeCol);
		  SxmlReplaceChild(nodeToTransform,newCol);
		  SxmlReset(nodeToTransform);
		  while(lineNode=SxmlNextNode(nodeToTransform))
		    {
		      MediaWikiAppendTextNodeFromList(wikiParser, newCol, SxmlLeafText(lineNode));
		    }
		  */
		  SxmlReplaceChild(nodeToTransform,newCol);
		  SxmlFree(nodeToTransform);
		}
	    }
	}

      if (listElemSet)
	{
	  i=0;
	  while ((col=listElemSet[i++]))
	    {
	      nameNodeCol[1]=col;
	      if ((nodeToTransform=SxmlGetFirstChildByTagName(inputRow,nameNodeCol)))
		{
		  SxmlNode *newCol;
		  SxmlNode *lineNode;
		  newCol=SxmlElementCreate(nameNodeCol);
		  SxmlReplaceChild(nodeToTransform,newCol);
		  SxmlReset(nodeToTransform);
		  while ((lineNode=SxmlNextNode(nodeToTransform)))
		    {
		      mediaWikiTableAppendElem(newCol, SxmlLeafText(lineNode));
		    }
		  SxmlFree(nodeToTransform);
		}
	    }
	}

      if (listLinkSet)
	{
	  i=0;
	  while ((col=listLinkSet[i++]))
	    {
	      nameNodeCol[1]=col;
	      if ((nodeToTransform=SxmlGetFirstChildByTagName(inputRow,nameNodeCol)))
		{
		  SxmlNode *newCol;
		  SxmlNode *lineNode;
		  newCol=SxmlElementCreate(nameNodeCol);
		  SxmlReplaceChild(nodeToTransform,newCol);
		  SxmlReset(nodeToTransform);
		  while ((lineNode=SxmlNextNode(nodeToTransform)))
		    {
		      char *lineText;
		      lineText=SxmlLeafText(lineNode);
		      if (lineText)mediaWikiTableAppendListLink(newCol, lineText);
		    }
		  SxmlFree(nodeToTransform);
		}
	    }
	}
      if (listCutSet)
	{
	  i=0;
	  while ((col=listCutSet[i++]))
	    {
	      nameNodeCol[1]=col;
	      if ((nodeToTransform=SxmlGetFirstChildByTagName(inputRow,nameNodeCol)))
		{
		  SxmlFree(nodeToTransform);
		}
	    }
	}
      if (listNewTagSet)
	{
	  SxmlReset( listNewTag);
	  i=0;
	  while ((col=listNewTagSet[i++]))
	    {
	      nameNodeCol[1]=col;
	      if ((nodeToTransform=SxmlGetFirstChildByTagName(inputRow,nameNodeCol)))
		{
		  SxmlNode *tagNode;
		  tagNode=SxmlNextNode(listNewTag);
		  SxmlReplaceName(nodeToTransform, SxmlLeafText(tagNode));
		}
	    }
	}
      SxmlPrint (SxmlInputRecord);
    }
  exit (EXIT_SUCCESS);
}
