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

/**********************************************************************
*
*  module   : Explor
*  fichier  : ExplorGenerParamStep2.c 
*  Auteur   : Jacques DUCLOY
*  Date     : fin 2013
*
***********************************************************************/

/*
    Third step of genating Area Data parameters
 */

#include <stdio.h>     /* for printf */
#include <stdlib.h>    /* for exit */
#include "Explor.h"
#include "Except.h"

extern char *optarg;
extern int   optind;
int getopt();

char *findType(char *stream, char*step, char *streamType, char *streamNameSpace, char *itemCode)
{
  char *targetType;
  char *indexType;
  if ((targetType=ExplorGetFromDictK5("Area", stream, step, itemCode, "hasType"))) return targetType;
  if ((targetType=ExplorGetFromDictK4(streamType, step, itemCode, "hasType"))) return targetType;
  if ((targetType=ExplorGetFromDictK4(streamType, "*", itemCode, "hasType"))) return targetType;
  if ((targetType=ExplorGetFromDictK4(streamNameSpace, step, itemCode, "hasType"))) return targetType;
  if ((targetType=ExplorGetFromDictK4(streamNameSpace, "*", itemCode, "hasType"))) return targetType;
  if ((targetType=ExplorGetFromDictK4("*", "*", itemCode, "hasType"))) return targetType;
  if ((indexType=ExplorGetFromDictK5("Area", stream, step, itemCode, "indexType"))) return itemCode;
  /* ExceptSetError("ExplorGenerParamStep2" ,"UN","no type for", itemCode ,"",1); */
  return  NULL;      
}

SxmlNode *findListTask(char *stream, char *typeStream,  char* typeStreamNS,  char *step, char *paramTask)
{
  char *listTaskStr;
  SxmlNode *listTask;
  static Buffer *bufTask=NULL;
  char *paramListTask;

  if (!bufTask) bufTask=NewBuffer();

  BufferStrcpy(bufTask, "list");
  BufferStrcat(bufTask, paramTask);
  paramListTask=BufferString(bufTask);
  listTaskStr=ExplorGetFromDictK4("Area", stream, step, paramListTask);
  if (!listTaskStr) 
    {
      listTaskStr=ExplorGetFromDictK3(typeStream, step, paramListTask);
      if (!listTaskStr) listTaskStr=ExplorGetFromDictK3(typeStreamNS, step,paramListTask);
      if (!listTaskStr) return NULL;
      ExplorSetDictK4("Area", stream, step, paramListTask, listTaskStr);
    }
  listTask=SxmlFromString(listTaskStr);
  return listTask;
}

SxmlNode *computeParameterAssoc(char *stream, char *typeStream,  char* typeStreamNS,  char *step)
{
  /* char *listAssocStr; */
  SxmlNode *listAssoc;
  SxmlNode *assocCodeNode;
  /*
  listAssocStr=ExplorGetFromDictK3(typeStream, step,"listAssoc");
  if(!listAssocStr)listAssocStr=ExplorGetFromDictK3(typeStreamNS, step,"listAssoc");
  if(!listAssocStr)return 0;

  ExplorSetDictK4("Area", stream, step, "listAssoc", listAssocStr);
  listAssoc=SxmlFromString(listAssocStr); */
  listAssoc= findListTask(stream, typeStream,  typeStreamNS, step, "Assoc");
  if (!listAssoc) return NULL;

  SxmlReset(listAssoc);
  while ((assocCodeNode=SxmlNextNode(listAssoc)))
    {
      char *assocCode;
      char *assocTypeKey;
      char *assocTypeStr;
      SxmlNode *assocTypeNode;
      char *fromIndexCode;
      assocCode=SxmlLeafText(assocCodeNode);
      assocTypeKey=findType(stream, step, typeStream, typeStreamNS, assocCode);
      if(!assocTypeKey) return NULL;
      assocTypeStr=ExplorGetFromDictK2(assocTypeKey, "assocType");
      ExplorSetDictK5 ("Area", stream, step , assocCode, "assocType", strdup(assocTypeStr));
      assocTypeNode=SxmlFromString(assocTypeStr);
      fromIndexCode=SxmlLeafText(SxmlNextSibling(SxmlGetFirstChildByTagName(assocTypeNode,"i"))); 
      ExplorSetDictK5 ("Area", stream, step , assocCode, "fromCode", fromIndexCode );
    }
  return listAssoc;
}

SxmlNode *computeParameterCross(char *stream, char *typeStream,  char* typeStreamNS,  char *step)
{
  SxmlNode *listCross;
  SxmlNode *crossCodeNode;
  /*
  listCrossStr=ExplorGetFromDictK3(typeStream, step,"listCross");
  if (!listCrossStr)listCrossStr=ExplorGetFromDictK3(typeStreamNS, step,"listCross");
  if (!listCrossStr) return 0;

  ExplorSetDictK4("Area", stream, step, "listCross", listCrossStr);
  listCross=SxmlFromString(listCrossStr);
  */
  /* listCrossCode=SxmlElementCreate("list"); */
  listCross= findListTask(stream, typeStream,  typeStreamNS, step, "Cross");
  if (!listCross) return NULL;

  SxmlReset(listCross);
  while ((crossCodeNode=SxmlNextNode(listCross)))
    {
      char *crossCode;
      char *crossTypeKey;
      char *crossTypeStr;
      char *crossTypeIdent; /* fromCodeToCode or builtin */
      SxmlNode *crossTypeNode;
      SxmlNode *crossFromValueNode;
      SxmlNode *crossToValueNode;
      char *fromIndexCode;
      char *toIndexCode;
      char *indexListFromStr;
      SxmlNode *indexListFrom;
      SxmlNode *toNode;

      crossCode=SxmlLeafText(crossCodeNode);
      crossTypeKey=findType(stream, step, typeStream, typeStreamNS, crossCode);
      if(!crossTypeKey)return NULL;
      crossTypeStr=ExplorGetFromDictK2(crossTypeKey, "crossType");
      ExplorSetDictK5 ("Area", stream, step , crossCode, "crossType", strdup(crossTypeStr));
      crossTypeNode=SxmlFromString(crossTypeStr);
      crossTypeIdent=SxmlLeafText(SxmlGetFirstChildByTagName(crossTypeNode,"i"));
      ExplorSetDictK5 ("Area", stream, step , crossCode, "crossTypeIdent", crossTypeIdent);
      if (strcmp(crossTypeIdent, "builtin")==0)ExplorSetDictK5 ("Area", stream, step , crossCode, "crossTypeKey", strdup(crossTypeKey));
      crossFromValueNode=SxmlNextSibling(SxmlGetFirstChildByTagName(crossTypeNode,"i"));
      crossToValueNode=SxmlNextSibling(crossFromValueNode);
      toIndexCode=SxmlLeafText(crossToValueNode);
      fromIndexCode=SxmlLeafText(crossFromValueNode);
      ExplorSetDictK5 ("Area", stream, step , crossCode, "toCode", toIndexCode );
      ExplorSetDictK5 ("Area", stream, step , crossCode, "fromCode", fromIndexCode );
      indexListFromStr=ExplorGetFromDictK5("Area", stream, step, fromIndexCode, "listCross");
      if(!indexListFromStr)
	{
	  indexListFrom=SxmlElementCreate("list");
	}
	else indexListFrom=SxmlFromString(indexListFromStr);
      SxmlAppendChild(indexListFrom, toNode=SxmlLeafCreate("to", toIndexCode));
      SxmlSetAttribute(toNode, "cross", crossCode);
      ExplorSetDictK5("Area", stream, step, fromIndexCode, "listCross", strdup(SxmlToString(indexListFrom)));
    }
  return listCross;
}

SxmlNode *computeParameterCluster(char *stream, char *typeStream,  char* typeStreamNS,  char *step)
{
  /* char *listClusterStr; */
  SxmlNode *listCluster;
  SxmlNode *clusterCodeNode;
  SxmlNode *indexListCluster;
  char *indexListClusterStr;
  char *clusterTypeKey;
  /* listClusterStr=ExplorGetFromDictK3(typeStream, step,"listCluster");
  if(!listClusterStr)listClusterStr=ExplorGetFromDictK3(typeStreamNS, step,"listCluster");
  if(!listClusterStr)return 0;

  ExplorSetDictK4("Area", stream, step, "listCluster", listClusterStr);
  listCluster=SxmlFromString(listClusterStr);
  */
  listCluster=findListTask(stream, typeStream,  typeStreamNS, step, "Cluster");
  if (!listCluster)return NULL;
  SxmlReset(listCluster);
  while ((clusterCodeNode=SxmlNextNode(listCluster)))
    {
      char *clusterCode;
      char *clusterTypeStr;
      SxmlNode *clusterTypeNode;
      char *fromAssocCode;
      char *fromIndexCode;

      clusterCode=SxmlLeafText(clusterCodeNode);
      clusterTypeKey=findType(stream, step, typeStream, typeStreamNS, clusterCode);
      if(!clusterTypeKey)return NULL;
      clusterTypeStr=ExplorGetFromDictK2(clusterTypeKey, "clusterType");
      if (!clusterTypeStr)
	{
	  ExceptSetError("ExplorGenerParamStep2" ,"UN","no type for cluster", clusterTypeKey ,"",1);
	  return NULL;
	}
      ExplorSetDictK5 ("Area", stream, step , clusterCode, "clusterType", strdup(clusterTypeStr));
      clusterTypeNode=SxmlFromString(clusterTypeStr);
      ExplorSetDictK5 ("Area", stream, step , clusterCode, "clusterAlgorihtm", SxmlLeafText(SxmlGetFirstChildByTagName(clusterTypeNode,"i")));
      fromAssocCode=SxmlLeafText(SxmlNextSibling(SxmlNextSibling(SxmlGetFirstChildByTagName(clusterTypeNode,"i")))); 
      ExplorSetDictK5 ("Area", stream, step , clusterCode, "fromAssoc", fromAssocCode);
      fromIndexCode=ExplorGetFromDictK5("Area", stream, step, fromAssocCode, "fromCode");
      ExplorSetDictK5 ("Area", stream, step , clusterCode, "fromIndex", fromIndexCode);
      if ((indexListClusterStr=ExplorGetFromDictK5("Area", stream, step , fromIndexCode, "listCluster")))
	indexListCluster=SxmlFromString(indexListClusterStr);
      else indexListCluster=SxmlElementCreate("list");
      SxmlAppendChild(indexListCluster, SxmlLeafCreate("i", clusterCode));
      ExplorSetDictK5 ("Area", stream, step , fromIndexCode, "listCluster", strdup(SxmlToString(indexListCluster)));
    }
  return listCluster;
}

void preComputeFacet()
     {
       char *preFacet;
       char *facetKey;
       char *currentFacet;
       SxmlNode *listFacet;
       SxmlNode *facetNode;

       static Buffer *bufVal=NULL;
       static Buffer *bufKey=NULL;
       static Buffer *bufOldKey=NULL;
       if(!bufVal) bufVal=NewBuffer();
       if(!bufKey) bufKey=NewBuffer();
       if(!bufOldKey) bufOldKey=NewBuffer();

       preFacet=StrDictKeyLessEqual(ExplorTableParam, "facet/");
       currentFacet=NULL;
       listFacet=NULL;
       
       while (preFacet)
	 {
	   char *posSl;
	   static Buffer *bufFacetName=NULL;
	   
	   if (!bufFacetName) bufFacetName=NewBuffer();

	   facetKey=StrDictNext(ExplorTableParam);
	   if (!facetKey)break;
	   if (strncmp(facetKey, "facet/", 6)!=0) break;
	   posSl=strchr(facetKey+7,'/');
	   if (!posSl)break;
	   BufferStrncpy(bufFacetName, facetKey+6, posSl-facetKey-6);
	   if (!(currentFacet) || (strcmp(BufferString(bufFacetName), currentFacet)!=0))
	     {
	       if (!listFacet)listFacet=SxmlElementCreate("list");
	       SxmlAppendChild(listFacet, facetNode=SxmlElementCreate("facet"));
	       SxmlSetAttribute(facetNode, "name", BufferString(bufFacetName));
	       currentFacet=SxmlGetAttribute(facetNode, "name");
	     }
	   preFacet=facetKey;
	 }
       if (!listFacet)return;
       SxmlReset(listFacet);
       while ((facetNode=SxmlNextNode(listFacet)))
	 {
	   char *facetForIndexStr;
	   currentFacet=SxmlGetAttribute(facetNode, "name");
	   facetForIndexStr=ExplorGetFromDictK3("facet", currentFacet, "facetForIndex");
	   if (facetForIndexStr)
	     {
	       SxmlNode *facetForIndexNode;
	       char *indexName;
	       facetForIndexNode=SxmlFromString(facetForIndexStr);
	       indexName=SxmlLeafText(SxmlFirstChild(facetForIndexNode));
	       ExplorSetDictK3("index", indexName, "hasFacet", strdup(currentFacet) );
	       ExplorSetDictK3("facet", currentFacet , "xPath", strdup( SxmlLeafText(SxmlLastChild(facetForIndexNode))) );
	       ExplorSetDictK3("facet", currentFacet , "index", strdup(indexName) );	       
	     }
	 }
       /*
       while (preFacet)
	 {
	   char *posSl;
	   SxmlNode *valNode;
	   facetKey=StrDictNext(ExplorTableParam);
	   BufferStrcpy(bufOldKey, facetKey);

	   if (strncmp(facetKey, "facet/", 6)!=0) break;
	   posSl=strchr(facetKey+7,'/');
	   if (!posSl)break;	 
	   if ((strcmp (posSl, "/facetForIndex")!=0))break;
	   BufferStrncpy(bufVal, facetKey+6, posSl-facetKey-6);

	   valNode=SxmlFromString(StrDictValue(ExplorTableParam));
	 
	   BufferStrcpy(bufKey, "index/");
	   BufferStrcat(bufKey, SxmlLeafText(SxmlFirstChild(valNode)));
	   BufferStrcat(bufKey, "/hasFacet");
	   StrDictSet(ExplorTableParam, strdup(BufferString(bufKey)),  strdup(BufferString(bufVal)));
	 

	   StrDictSearch(ExplorTableParam, BufferString(bufOldKey));
	   preFacet=StrDictKey(ExplorTableParam);
	 }
       */
     }


int main (int argc, char **argv) {
   int cOption;
   SxmlNode *streamNode;
   SxmlNode *mainStreamNode;
   char *pathParamFile;
   SxmlNode *areaListNS;
   SxmlNode *areaListTypeStream;

   while((cOption=getopt(argc,argv,"t:"))!=EOF)
     {switch (cOption)
	 {
	 case 't':
	   pathParamFile=optarg;
	   break;
	 }
     }

   ExplorParamInit(pathParamFile);
   areaListNS=SxmlElementCreate("list");
   areaListTypeStream=SxmlElementCreate("list");

   preComputeFacet();

   SxmlReset(ExplorAreaData);
   /* while (streamNode=SxmlNextNode(ExplorListStream)) */
   while ((streamNode=SxmlNextNode(ExplorAreaData)))
     {
       char *stream;
       char *typeStream;
       static Buffer *typeStreamBufNS=NULL;
       char *listStepStr;
       SxmlNode *streamListSteps;
       SxmlNode *typeStreamListStreams;
       SxmlNode *stepNode;
       char     *typeStreamListStreamsStr;
       SxmlNode *typeStreamNSListStreams;
       char     *typeStreamNSListStreamsStr;
       char *posColon;
       char *typeStreamNS;
       char *streamCode;

       /* stream=SxmlLeafText(streamNode); */
       streamCode= SxmlGetAttribute(streamNode, "code");
       stream=streamCode;

       typeStream=ExplorGetFromDictK3 ("Area", stream, "typeStream");
       SxmlSetAttribute(streamNode, "type", typeStream);

       SxmlAppendChild(areaListTypeStream, SxmlLeafCreate("i", typeStream));
       if (!typeStreamBufNS)typeStreamBufNS=NewBuffer();
       BufferStrcpy(typeStreamBufNS, typeStream);
       if ((posColon=strchr(BufferString(typeStreamBufNS),':'))) posColon[0]='\0';
       typeStreamNS=BufferString(typeStreamBufNS);

       listStepStr=ExplorGetFromDictK2(typeStream, "listSteps");
       streamListSteps=SxmlFromString(listStepStr);       
       ExplorSetDictK3("Area", stream, "listSteps", listStepStr );

       if (strcmp(stream, "Main")==0)
	 {
	   if (!streamListSteps) ExceptSetError("Explor", "NS" ,"streamListSteps missing for stream Main", "", "", 1);
	   ExplorSetDictK2("Area","mainLastStep", SxmlLeafText(SxmlLastChild(streamListSteps)));
	   mainStreamNode=streamNode;
	 }

       if ((typeStreamListStreamsStr=ExplorGetFromDictK2(typeStream, "listStreams")))
	 {
	   typeStreamListStreams=SxmlFromString(typeStreamListStreamsStr);
	 }
       else
	 {
	   typeStreamListStreams=SxmlElementCreate("list");
	 }
       SxmlAppendChild(typeStreamListStreams, SxmlLeafCreate("i",stream));
       ExplorSetDictK2(strdup(typeStream), "listStreams", strdup(SxmlToString(typeStreamListStreams)));

       if ((typeStreamNSListStreamsStr=ExplorGetFromDictK2(BufferString(typeStreamBufNS), "listStreams")))
	 {
	   typeStreamNSListStreams=SxmlFromString(typeStreamNSListStreamsStr);
	   SxmlAppendChild(typeStreamNSListStreams, SxmlLeafCreate("i",stream));
	   ExplorSetDictK2(BufferString(typeStreamBufNS), "listStreams", strdup(SxmlToString(typeStreamNSListStreams)));
	 }
       else
	 {
	   typeStreamNSListStreams=SxmlElementCreate("list");
	   SxmlAppendChild(typeStreamNSListStreams, SxmlLeafCreate("i",stream));
	   ExplorSetDictK2(strdup(BufferString(typeStreamBufNS)), "listStreams", strdup(SxmlToString(typeStreamNSListStreams)));
	   SxmlAppendChild(areaListNS, SxmlLeafCreate("i", BufferString(typeStreamBufNS)));
	 }

       if (!streamListSteps) ExceptSetError("Explor", "NS" ,"streamListSteps missing for stream", stream, "", 1);
       SxmlReset(streamListSteps);
       while ((stepNode=SxmlNextNode(streamListSteps)))
	 {
	   char *step;
	   /* char *listIndexStr; */
	   SxmlNode *indexCodeNode;
	   char *listIndexesStr;
	   SxmlNode *listIndexes;
	   SxmlNode *listIndexesCode;
	   SxmlNode *treeStepNode;
	   char      *stepCode;

	   stepCode=SxmlLeafText(stepNode);
	   step=stepCode;

	   SxmlAppendChild(streamNode, treeStepNode=SxmlElementCreate("step"));
	   SxmlSetAttribute(treeStepNode, "code", stepCode); 

	   listIndexes=findListTask(stream, typeStream,  typeStreamNS, step, "Indexes");

	   if(listIndexes)
	     {
	       char      *addIndexesStr;
	       if ((addIndexesStr=ExplorGetFromDictK4("Area", stream, step,"addIndexes")))
		 {
		   SxmlNode *addIndexes;
		   SxmlNode *newIndex;
		   addIndexes=SxmlFromString(addIndexesStr);
		   SxmlReset(addIndexes);
		   while ((newIndex=SxmlNextNode(addIndexes)))
		     {
		       SxmlAppendChild(listIndexes, SxmlClone(newIndex));
		     }
		 }
	       listIndexesStr=strdup(SxmlToString(listIndexes));

	       if(addIndexesStr)ExplorSetDictK4("Area", stream, step, "listIndexes", listIndexesStr);

	       ExplorSetDictK4("Area", stream, step, "listIndexCode", listIndexesStr);
	       listIndexesCode=SxmlElementCreate("list");

	       SxmlReset(listIndexes);
	       while ((indexCodeNode=SxmlNextNode(listIndexes)))
		 {
		   char *nameType;
		   char *indexType;
		   char *indexCode;
		   SxmlNode *treeIndexNode;

		   indexCode=SxmlLeafText(indexCodeNode);
		   nameType=findType(stream, step, typeStream, typeStreamNS, indexCode);
		   if (!nameType)continue;

		   SxmlAppendChild(treeStepNode, treeIndexNode=SxmlElementCreate("index"));
		   SxmlSetAttribute(treeIndexNode, "code", indexCode);

		   indexType=ExplorGetFromDictK2(nameType, "indexType");
		   if (!indexType) indexType=ExplorGetFromDictK5("Area", stream, step, indexCode, "indexType");
		   if (!indexType) 
		     {
		       ExceptSetError("ExplorGenerParamStep2", "NK","Key indexType for", nameType , " not founded or not fit.",1);
		       exit(1);
		     }
		   ExplorSetDictK2 ("indexParamName", indexCode, strdup(indexType)); 
		   ExplorSetDictK5 ("Area", stream, step , indexCode, "indexType", strdup(indexType));
		 }

	       SxmlReset(listIndexes);
	       while ((indexCodeNode=SxmlNextNode(listIndexes)))
		 {
		   char *facetCode;
		   char *indexCode;
		   SxmlNode *treeIndexNode;
		   static Buffer *bufKey=NULL;

		   if (!bufKey) bufKey=NewBuffer();

		   indexCode=SxmlLeafText(indexCodeNode);
		   facetCode=ExplorGetFromDictK3( "index", indexCode,  "hasFacet");
		   if (facetCode)
		     {
		       SxmlAppendChild(treeStepNode, treeIndexNode=SxmlElementCreate("facet"));
		       SxmlSetAttribute(treeIndexNode, "code", facetCode);
		     }
		   
		 }

	     }

	   computeParameterAssoc(stream, typeStream, typeStreamNS, step);
           computeParameterCross(stream, typeStream, typeStreamNS, step);
           computeParameterCluster(stream, typeStream, typeStreamNS, step);
	 }      
     }
   ExplorSetDictK2("Area", "listNS", strdup(SxmlToString(areaListNS)));
   ExplorSetDictK2("Area", "listTypeStream", strdup(SxmlToString(areaListTypeStream)));

   {  /* listZooms */
     SxmlNode *zoomNode;
     if ((mainStreamNode) && (zoomNode=SxmlNextSibling(mainStreamNode)))
       {
	 SxmlNode *listZooms;
	 listZooms=SxmlElementCreate("list");
	 while (zoomNode)
	   {
	     SxmlAppendChild(listZooms, SxmlClone(zoomNode));
	     zoomNode=SxmlNextSibling(zoomNode);
	   }
	 ExplorSetDictK2("Area", "listZooms", strdup(SxmlToString(listZooms)));
       }
   }

   {  /* listUpStreams */
     if ((mainStreamNode) && (SxmlPreviousSibling(mainStreamNode)))
       {
	 SxmlNode *parentNode;
	 SxmlNode *upNode;
	 SxmlNode *listUpStreams;
	 parentNode=SxmlParent(mainStreamNode);
	 listUpStreams=SxmlElementCreate("list");
	 SxmlReset(ExplorListStream);
	 upNode=SxmlFirstChild(parentNode);
	 while (upNode)
	   {
	     if (upNode==(mainStreamNode))break;
	     SxmlAppendChild(listUpStreams, SxmlClone(upNode));
	     upNode=SxmlNextSibling(upNode);
	   }
	 ExplorSetDictK2("Area", "listUpStreams", strdup(SxmlToString(listUpStreams)));
       }
   }
   
   ExplorSetDictK2("Area", "areaTree", strdup(SxmlToString(ExplorAreaTree)));
   ExplorSaveParamTable("AreaParam.data", NULL);
   printf("<?dilib file=\"%s/Input/AreaDataTree.xml\" ?>\n", ExplorAreaDir );
   SxmlPrint(ExplorAreaTree);
   putchar('\n');
      /*generInitParamTab(); */
   exit(EXIT_SUCCESS);
}
