#include <stdio.h>
#include <string.h>
#include "defn.h"
#include "newString.h"
#include "stretchArray.h"
#include "extGlobal.h"
#include "extFuncDefn.h"

StretchArray<String> headers(20,5);
int                  count  = 0;
StretchArray<String> xheaders(20,5);
int                  xcount = 0;
StretchArray<String> arcFunc(20,100);
int                  fcount = 0;

void
processHeader(char* str, bool flag)
{
    char buff[1024];
    sprintf(buff, "#include%s", str);

    if (!count)
    {
        fprintf(cltFP, "%s", DEFAULT_HEADERS );
    }

    if (flag)
    {
        fprintf(cltFP, "%s", buff);
        fflush(cltFP);
        headers[ count++ ] = buff;
    }
    else // an xheader ?? start mask
    {
        int len = strlen(str);
        if ( str[ len - 3 ] == '.' && str[ len - 2 ] == 'x' )
        {
            int i = 0;
            int j = 0;
            while( isBlank(str[ i++ ]) )
                         ;

            while(str[ i ] != '"')
            {
                buff[ j++ ] = str[ i++ ];
            }

            buff[ j  ] = '\0';
            xheaders[ xcount++ ] = buff;
        } 
        else // Masking of Xheaders RKJ end mask 

        {
            fprintf(cltFP, "%s", buff);
            fflush(cltFP);
        }
    }
}

void
openServerFile(char* funcName)
{
    char buff1[ 208 ];
    char buff2[ 208 ];

    getExtension(buff1, fileName, ""); 
    sprintf(buff2, "_%s_%s_proc.c", buff1, funcName);
    oserFP = efopen("Otherfunc", "w");
    serFP = efopen("DontCare", "w");
	newserFP = fopen (buff2, "w");

    //fprintf(serFP, "%s", DEFAULT_HEADERS );

    for(int i = 0; i < count; i++)
    {
       fprintf(newserFP, "%s\n",  headers[ i ].GetString() );
    }

    fprintf(newserFP, "#include <Coordinator.h>\n");
    sprintf(buff2, "#include \"_%s_%s.h\"", buff1, funcName); 
    fprintf(newserFP, "\n%s\n\n", buff2);
    fprintf(newserFP, "extern int prognum;\n");
    fprintf(newserFP, "%sResults  %sRes; \n", funcName, funcName);
    fprintf(newserFP, "LongArr longArr; \n");
    fprintf(newserFP, "static struct timeval TIMEOUT = {0, 0}; \n");
	fprintf(newserFP, "void SetParam(int,int,int);\n");
}

void
writeFuncDefn(char* funcName, char* vars, char* retType)
{
    char  buff1[ 256 ];
    char  buff2[ 256 ];
    char  buff3[ 256 ];
    FILE *rpcFP;


    fprintf(cltFP, "%s\n%s( %s )\n", retType, funcName, vars);

    sprintf(buff3, "%s %s %s", retType, funcName, vars);
    arcFunc[ fcount++ ] = buff3;

    fprintf(serFP, "%s\n%s( %s )\n", retType, funcName, vars);  
    
    getExtension(buff1, fileName, "");
    sprintf(buff2, "_%s_%s.x", buff1, funcName);
    rpcFP = efopen(buff2, "w");

    fprintf(rpcFP, "typedef char Str<>; \n");

    // Begin mask ------------------------ RKJ
	for(int i = 0; i < xcount; i++)
    {

	//printf(" eopen file -- %s \n",xheaders[ i ].GetString());
        FILE* xfp = efopen(xheaders[ i ].GetString(), "r");
        int   num = 0;

        while(1)
        {
            num = fread(buff1, sizeof(char), sizeof(buff1) - 1, xfp);
            buff1[ num ] = '\0';
            fprintf(rpcFP, "%s", buff1);
            if (num  != sizeof(buff1) - 1)
            {
                break;
            }
        }

        fprintf(rpcFP, "\n");
        fclose( xfp );
    }
	 //End mask-------RKJ

    fprintf(rpcFP, "struct %sArguments\n{\n\t ", funcName);
    for(int i = 0; vars[i] != '\0'; i++)
    {
        if(vars[i] != ',')
        {
            fputc(vars[i], rpcFP);
        }
        else
        {
            fprintf(rpcFP,";\n\t");
        }
    }
    fprintf(rpcFP, ";\n\t int RibId;\n\t int Pid;\n\t int NodeId;\n");
    fprintf(rpcFP, "\t Str NodeName;\n};\n\n");

    fprintf(rpcFP, "struct %sResults\n{\n\t %s res;\n};\n\n",
                                                 funcName, retType);
    
    getExtension(buff1, buff2, "");
    fprintf(rpcFP, "program ARC%s\n{\n", buff1);

    upperStr(buff2, buff1); 

    fprintf(rpcFP, "\tversion VER1\n\t{\n");
    fprintf(rpcFP, "\t\tvoid\t\t SEND_%d%s_ARGS(%sArguments ) = 1;\n",
                                    fcount - 1, buff2, funcName);
    fprintf(rpcFP, "\t\t%sResults\t\t GET_%d%s_RESULT(void ) = 2;\n",
                                      funcName, fcount - 1, buff2);
    fprintf(rpcFP, "\t\tvoid\t\t KILL_%d%s(void ) = 3;\n",
                                    fcount - 1, buff2);
    fprintf(rpcFP, "\t} = 1;\n} = 0x12345678; ");
    fclose(rpcFP);
}

void produceProcFile (void) {

char buff [100];


};

void
writeOtherFunc(char* funcName, char* vars, char* retType)
{
    char buff[ 512 ];
    char buff1[50];
    char* tok;
    int flag;


    getExtension(buff, fileName, ""); 
    lowerStr(buff1, buff);
    lowerStr(buff, funcName);

    fprintf(oserFP, "\n\n#ifdef NEW_VER_RPC\n\n");
    fprintf(oserFP,
      "void*\nsend_%d_%s_%s_args_1_svc(%sArguments* arg, struct svc_req* dum)\n\n",
                         fcount - 1, buff1, buff, funcName);
    fprintf(oserFP, "#else\n\n");
    fprintf(oserFP, "void*\nsend_%d_%s_%s_args_1(%sArguments* arg)\n\n",
                          fcount - 1, buff1, buff, funcName);
    fprintf(oserFP, "#endif\n{");
    fprintf(oserFP, "\tCLIENT *cl;\n");
    fprintf(oserFP, "\t%s* res;\n", retType);

    fprintf(oserFP, "\tres = (%s *) malloc( sizeof(%s)); \n", retType, retType);

    fprintf(oserFP, "\tlongArr.LongArr_len = 3;\n");
    fprintf(oserFP, "\tlongArr.LongArr_val = (u_long *) malloc ( 3 * sizeof(u_long));\n");
    fprintf(oserFP, "\tlongArr.LongArr_val[0] = arg->RibId; \n");
    fprintf(oserFP, "\tlongArr.LongArr_val[1] = arg->Pid; \n");
    fprintf(oserFP, "\tlongArr.LongArr_val[2] = prognum;\n");

    fprintf(oserFP, "\t *res = %s( ", funcName);
    tok = strtok( vars, ", \t\n");
    flag = 1;
    while( flag && (tok != NULL))
    {
        tok = strtok( NULL, ", \t\n");
        fprintf(oserFP, "arg->%s", tok);
        if( (tok = strtok( NULL, ", \t\n")) != NULL)
        {
            fprintf(oserFP, ", ", tok);
        }
        else
        {
            flag = 0;
        }
    }
    fprintf(oserFP, "); \n");

    fprintf(oserFP, "\tmemcpy(&%sRes.res, res,sizeof(%s)); \n", funcName,
            retType);

    fprintf(oserFP, "\tif ((cl = clnt_create(arg->NodeName.Str_val, \n"); 
            fprintf(oserFP, "\t\t\tCOORDINATOR, USER_INTERACTION, \"tcp\")) == NULL)\n");
    fprintf(oserFP, "\t{\n");
        fprintf(oserFP, "\t\tclnt_pcreateerror(arg->NodeName.Str_val);\n");
    fprintf(oserFP, "\t}\n");
    
    fprintf(oserFP, "\tclnt_call(cl,  RESULT_INTIMATION, xdr_LongArr, &longArr, \n");
            fprintf(oserFP, "\t\t\txdr_void, NULL, TIMEOUT);\n");

    fprintf(oserFP, "\tclnt_destroy(cl);\n");
fprintf(oserFP, "}\n\n");

fprintf(oserFP, "#ifdef NEW_VER_RPC \n");

fprintf(oserFP, "%sResults*\n", funcName ); 
fprintf(oserFP, "get_%d_%s_%s_result_1_svc(void* arg, struct svc_req* dum) \n", 
        fcount - 1, buff1, buff);

fprintf(oserFP, "#else\n");

fprintf(oserFP, "%sResults*\n", funcName ); 
fprintf(oserFP, "get_%d_%s_%s_result_1(void* arg) \n", fcount - 1, buff1,
        buff);
    
fprintf(oserFP, "#endif\n");
fprintf(oserFP, "{\n");
    fprintf(oserFP, "\treturn &%sRes;\n", funcName); 
fprintf(oserFP, "}\n\n");

fprintf(oserFP, "#ifdef NEW_VER_RPC\n");

fprintf(oserFP, "void*\n"); 
fprintf(oserFP, "kill_%d_%s_%s_1_svc(void* arg, struct svc_req* dum)\n",
        fcount - 1, buff1, buff);

fprintf(oserFP, "#else\n");

fprintf(oserFP, "void* \n");
fprintf(oserFP, "kill_%d_%s_%s_1(void* arg)\n", fcount - 1, buff1, buff);
    
fprintf(oserFP, "#endif\n");
fprintf(oserFP, "{\n");
    fprintf(oserFP, "\tkill( getpid(), SIGKILL);\n");
fprintf(oserFP, "}\n");

    fclose(newserFP);
    fclose(oserFP);
    fclose(serFP);
}

StretchArray<String> syncVars(50,10);
int                  scount  = 0;

void
saveSyncVar(char* var)
{
    for (int k = 0; k < scount; k++)
    {
         if (strcmp(var, syncVars [ k ].GetString()) == 0)
         {
            fprintf(stderr,
                 "%s: warning: redeclaration of sync variable %s\n",
                             progName, var);
            return;
         }
    }

    syncVars[ scount++ ] = var;
}

void
processArcFuncCall(char* var, char* fcall)
{
    char* list[ 512 ];
    int   args = flatten(list, fcall, ' ');
    int   i;
    int   j;
    int   blocking = 1;  
    int   funcId;  
    char  buff[50];  
    char  buff3[256];  
    char* tok;   
       
    tok = strtok( var, "[ \t\n");
    
    for(i = 0; i < scount; i++)
    {
        if(!strcmp( syncVars[i].GetString(), tok))
        {
            blocking = 0;
            
        }
    }

	//printf("In process Arc function call.....\n");  //Aruna
    for(i = 0; i < fcount; i++)
    {
        strcpy( buff3, arcFunc[i].GetString());
        tok = strtok( buff3, ", \t\n");
        tok = strtok( NULL, ", \t\n");
        //printf( "%s \t", tok);  //Aruna
        if( !strcmp( list[0], tok))
        {
            funcId = i;
            break;
        } 
    }
    
    getExtension(buff, fileName, "");
    //printf( "%s \t", buff3);  //Aruna
    //printf("%s := %s %d\n", var, fcall, args); //Aruna


    fprintf(cltFP, "/* Here the code for ARC FUNC CALL will come */ \n");

    fprintf(cltFP, " \t\tIncrCurLockId(); \n");
    fprintf(cltFP, " \t\tSync[i].RibId = RibId; \n");
    fprintf(cltFP, " \t\tSetRibParam( RibId); \n");
        
    fprintf(cltFP, "\t\tBuffer[RibId].Status = NotAvailable; \n");
    fprintf(cltFP, "\t\tBuffer[RibId].LockId = GetCurLockId(); \n");
    fprintf(cltFP, "\t\tstrcpy( Buffer[RibId].FuncName , \"_%s_%s\" ); \n", 
            buff, list[0]);
    fprintf(cltFP, "\t\tBuffer[RibId].FuncType  = ARC_%s; \n", 
            list[0]);
    fprintf(cltFP, "\t\ttime(&Buffer[RibId].StartTime); \n");
    fprintf(cltFP, "\t\tBuffer[RibId].RetriesMade = 0; \n");
    fprintf(cltFP, "\t\tstrcpy( Buffer[RibId].Directives, %sDirectives); 
            \n", list[0]);
        

    for( i = 1; i < args;  i++)
    {
        tok = strtok( NULL, ", \t\n");
        tok = strtok( NULL, ", \t\n");
        fprintf(cltFP, " \t\tmemcpy(&%sArgs.%s, &%s, sizeof(%s)); \n",
                list[0], tok, list[i], list[i]);
    }

    fprintf(cltFP, " \t\tmemcpy(&%sArgs.RibId, &RibId, sizeof(int)); \n", list[0]);
    fprintf(cltFP, " \t\tmemcpy(&%sArgs.Pid, &pid, sizeof(int));\n", list[0]);

    fprintf(cltFP, " \t\tif( Buffer[RibId].LockId >= 0) \n");
    fprintf(cltFP, " \t\t{\n");
        fprintf(cltFP, " \t\t\tlockList->LocalLockArr_val[Buffer[RibId].LockId].Status = ALLOCATED; \n");
        fprintf(cltFP, " \t\t\tlockList->LocalLockArr_val[Buffer[RibId].LockId].RibId= RibId;\n");
    fprintf(cltFP, " \t\t}\n");

    fprintf(cltFP, " \t\tmemcpy(&%sArgs.NodeName, &(str), sizeof(Str));\n", list[0]);

    fprintf(cltFP, " \t\tBuffer[RibId].Arguments = (char *) malloc( sizeof(%sArgs)); \n", list[0]);
    fprintf(cltFP, " \t\tmemcpy(Buffer[RibId].Arguments, (char *)&%sArgs, sizeof( %sArgs)); \n", list[0], list[0]);
        
           
    fprintf(cltFP, " \t\tBuffer[RibId].ProgNum = PostRibServer(RibId, getpid());\n");
    fprintf(cltFP, " \t\tsleep(3);\n");
    //fprintf(cltFP, " \t\tsleep(30);\n");
    fprintf(cltFP, " \t\tPostArgs( RibId);\n");

    if( blocking)
    {
    fprintf(cltFP, "\t\tWaitOnSync(RibId, &%s, sizeof(%s)); \n", var,
            var);
    /*
        fprintf(cltFP, "\t\ttime(&presentTime);\n");

        fprintf(cltFP, "\t\twhile(((presentTime - Buffer[RibId].StartTime) < Buffer[RibId].Timeout) \n");
            fprintf(cltFP, "\t\t\t\t&& (Buffer[RibId].RetriesMade < Buffer[RibId].Retries)) \n");
    fprintf(cltFP, "\t\t{\n");
        fprintf(cltFP, "\t\t\tif ( Buffer[RibId].Status == Available)\n");
        fprintf(cltFP, "\t\t\t{\n");
            fprintf(cltFP, "\t\t\t\tmemcpy (&%s, Buffer[RibId].Results, sizeof(%s)); \n", var, var);
            fprintf(cltFP, "\t\t\t\tif(  Buffer[RibId].LockId > -1) \n");
            fprintf(cltFP, "\t\t\t\t{\n");
                fprintf(cltFP, "\t\t\t\t\tSetLockFree(  Buffer[RibId].LockId); \n");
            fprintf(cltFP, "\t\t\t\t}\n");
            fprintf(cltFP, "\t\t\t\tbreak;\n");
        fprintf(cltFP, "\t\t\t}\n");
        fprintf(cltFP, "\t\t\tmessageHandler();\n");
    fprintf(cltFP, "\t\t}\n");

    fprintf(cltFP, "\t\tif ( Buffer[RibId].Status == NotAvailable)\n");
    fprintf(cltFP, "\t\t{\n");
        fprintf(cltFP, "\t\t\tif(Buffer[RibId].LocalExec) \n",tok);
        fprintf(cltFP, "\t\t\t{\n");

    fprintf(cltFP, "\t\t\t\tBuffer[RibId].LockId = -1; \n");
    fprintf(cltFP, " \t\t\t\tBuffer[RibId].ProgNum = PostRibServer(RibId, getpid());\n");
    fprintf(cltFP, " \t\t\t\tsleep(1);\n");
    fprintf(cltFP, " \t\t\t\tPostArgs( RibId);\n");

        fprintf(cltFP, "\t\t\t}\n");
    fprintf(cltFP, "\t\t}\n");
    */
    }

    fprintf(cltFP, " \t\tRibId++;\n");
}

void
processSync(char* pair)
{
    char* tok;
    char* tok1;
    char* tok2;
    
    //printf("Vars %s\n", pair); //Aruna
    fprintf(cltFP, "/* Here the code for SYNC FUNC CALL will come */ \n");

    tok = strtok( pair, ", \t\n");
    tok1 = strtok( NULL, ", \t\n");
    tok2 = strtok( tok1, "& \t\n");
    fprintf(cltFP, "\t\tWaitOnSync(%s.RibId, %s, sizeof(%s)); \n", tok,
            tok1, tok2);

  /*
    fprintf(cltFP, "\t\ttime(&presentTime);\n");
    fprintf(cltFP, "\t\twhile(((presentTime - Buffer[%s.RibId].StartTime) < Buffer[%s.RibId].Timeout) \n",
            tok, tok);
            fprintf(cltFP, "\t\t\t\t&& (Buffer[%s.RibId].RetriesMade <= Buffer[%s.RibId].Retries)) \n",
                    tok, tok);
    fprintf(cltFP, "\t\t{\n");
        fprintf(cltFP, "\t\t\tif ( Buffer[%s.RibId].Status == Available)\n",tok);
        fprintf(cltFP, "\t\t\t{\n");
            fprintf(cltFP, "\t\t\t\tmemcpy (%s, Buffer[%s.RibId].Results, sizeof(%s)); \n", tok1, tok, tok2);
            fprintf(cltFP, "\t\t\t\tif(  Buffer[%s.RibId].LockId > -1) \n",tok);
            fprintf(cltFP, "\t\t\t\t{\n");
                fprintf(cltFP, "\t\t\t\t\tSetLockFree(  Buffer[%s.RibId].LockId); \n", tok);
            fprintf(cltFP, "\t\t\t\t}\n");
            fprintf(cltFP, "\t\t\t\tbreak;\n");
        fprintf(cltFP, "\t\t\t}\n");
        fprintf(cltFP, "\t\t\tmessageHandler();\n");
    fprintf(cltFP, "\t\t}\n");

    fprintf(cltFP, "\t\tif ( Buffer[%s.RibId].Status == NotAvailable)\n", tok);
    fprintf(cltFP, "\t\t{\n");
        fprintf(cltFP, "\t\t\tif(Buffer[%s.RibId].LocalExec) \n",tok);
        fprintf(cltFP, "\t\t\t{\n");
    fprintf(cltFP, "\t\t\t\tBuffer[%s.RibId].LockId = -1; \n", tok);
    fprintf(cltFP, " \t\t\t\tBuffer[%s.RibId].ProgNum = PostRibServer(%s.RibId, getpid());\n", tok, tok);
    fprintf(cltFP, " \t\t\t\tsleep(1);\n");
    fprintf(cltFP, " \t\t\t\tPostArgs( %s.RibId);\n", tok);

    fprintf(cltFP, " \t\t\t\twhile( Buffer[%s.RibId].Status != Available)\n", tok);
    fprintf(cltFP, " \t\t\t\t{\n");
	    fprintf(cltFP, " \t\t\t\t\tmessageHandler(); \n");
	    fprintf(cltFP, " \t\t\t\t\tif( Buffer[%s.RibId].Status == Available) \n", tok);
        fprintf(cltFP, " \t\t\t\t\t{\n");
		    fprintf(cltFP, " \t\t\t\t\t\tmemcpy (&tmpz, Buffer[%s.RibId].Results, sizeof(tmpz)); \n", tok);
			fprintf(cltFP, " \t\t\t\t\tif\t(  Buffer[%s.RibId].LockId > -1) \n", tok);
			fprintf(cltFP, " \t\t\t\t\t\t{\n");
			    fprintf(cltFP, " \t\t\t\t\t\t\tSetLockFree(  Buffer[%s.RibId].LockId); \n", tok); 
			fprintf(cltFP, " \t\t\t\t\t\t}\n");
        fprintf(cltFP, " \t\t\t\t\t}\n");
    fprintf(cltFP, " \t\t\t\t}\n");
        fprintf(cltFP, "\t\t\t}\n");
    fprintf(cltFP, "\t\t}\n");
    */
}

void
processSyncAnd(char* pairs)
{
    int i;
    char* list[ 512 ];
    int   args = flatten(list, pairs, ' ');
    char*   tok;
    
    printf("Vars %s\n", pairs);

    fprintf(cltFP, "/* Here the code for SYNCAND FUNC CALL will come */ \n");
    fprintf(cltFP, "\t\tWaitOnSyncAnd( %d", args/2);

    for( i = 0; i < args/2; i++)
    {
        tok = strtok( list[2 * i + 1], "& \t\n");
        fprintf(cltFP, ", %s.RibId, %s, %s", list[2 * i], list[2 * i + 1],
                tok);
    }
    fprintf(cltFP, "); \n");
}

void
processSyncOr(char* pairs)
{
    char* list[ 512 ];
    int   args = flatten(list, pairs, ' ');
    printf("Vars %s %d \n", pairs, args);
    fprintf(cltFP, "/* Here the code for SYNCOR FUNC CALL will come */");
}

void
processSyncAll(void)
{
    fprintf(cltFP, "/* Here the code for SYNCALL FUNC CALL will come */");
}

void  processSyncAny(void)
{
    fprintf(cltFP, "/* Here the code for SYNCANY FUNC CALL will come */");
}

