#!/usr/bin/env python3
# Take a .in file and generate :
# pref.cpp which is a loader/saver file + associated structure
# (c) Mean 2011
#
#  const char *name
#  type
#  char *current_val
#  const char *default
#  const char *min
#  const char *max
#
import os
import re
import sys

structName=r'prefs_list'
allCTypes=dict()
allATypes=dict()
allJTypes=dict()


allJTypes["uint32_t"]="json.addUint32("
allJTypes["int32_t"]="json.addInt32("
allJTypes["bool"]="json.addBool("
allJTypes["string"]="json.addString("
allJTypes["float"]="json.addFloat("
allJTypes["filename"]="json.addString("


allATypes["uint32_t"]="ADM_param_uint32_t"
allATypes["int32_t"] ="ADM_param_int32_t "
allATypes["float"]   ="ADM_param_float   "
allATypes["bool"]    ="ADM_param_bool    "
allATypes["string"]  ="ADM_param_stdstring  "
allATypes["filename"]="ADM_param_stdstring  "

fullPath=""
nested=list()
gotName=False
def usage():
    print("python pref_gen.py xxxx.in")
#########################################################
def outputJson(st):
    jsonFile.write(str(st)+"\n")
    #print(st)
    pass
def outputList(st):
    listFile.write(str(st)+"\n")
    #print(st)
    pass

#

#
def makeStructure(varType,params):
    if(len(params)<2):
        print("Not enough parameter for line "+str(varName))
        exit(1)
    min=0
    max=100
    default=20
    #print varType
    #print params
    nbParam=len(params)
    varName=params[0]
    default=str(params[1])
    default=re.sub(r'"',r'',default)
    default="\""+str(default)+"\""
    if(nbParam==2):
        if(varType!="string" and varType!="filename"):
            print ("Error "+str(varName)+" has not the good number of parameters,type="+str(varType))
            raise
        min=r"0"
        max=r'0'
    elif(nbParam==4):
        min=str(params[2])
        max=str(params[3])
    if(not varType in allATypes):
        print("json:Unknown var type <"+str(varType)+str(">"))
        exit(1)
    if(len(fullPath)==0):
        fullName=varName
    else:
        fullName=fullPath+"_"+varName
    if(len(fullPath2)==0):
        fullName2=varName
    else:
        fullName2=fullPath2+"."+varName
    out= "{ "+str(fullName.upper())+str(",\"")+str(fullName2)+str("\"")
    l=len(out)
    mx=70
    if(l>mx):
        pass
    else:
        out=out+(mx-l)*" "
    out=out+","+str(allATypes[varType])
    out=out+"\t,"+str(default)+",\t"+str(min)+",\t"+str(max)
    out=out+"},"
    outputJson(out)
    outputList(fullName.upper()+", \t//"+str(varType))
###################################################################################################################################

def writeJsonHead():
    outputJson("// automatically generated by pref_gen.py, do not edit!")
    outputJson("#if 0")
    outputJson("typedef struct")
    outputJson("{")
    outputJson("   const char *name;")
    outputJson("   TYPE  type;")
    outputJson("   const char *defaultValue;")
    outputJson("   const char *min;")
    outputJson("   const char *max;")
    outputJson("   char *Value;")
    outputJson("}optionDesc;")
    outputJson("#endif ")
    outputJson("static optionDesc myOptions[]={")
def writeJsonFooter():
    outputJson("};\n")

###################################################################################################################################
# Main...
###################################################################################################################################
nb=len(sys.argv)
if(nb!=2):       
    usage()
    exit(1)
print("Processing "+str(sys.argv[1]))
inputFile=sys.argv[1]
if(not os.path.isfile(inputFile)):
    print("no such file "+str(inputFile))
    exit(1)
jsonFileName=re.sub(r'.conf',r'_pref.h',inputFile)
listFileName=str("../include/")+re.sub(r'.conf',r'_list.h',inputFile)
print("Generating "+jsonFileName)
jsonFile=open(jsonFileName,'w')
print("Generating "+listFileName)
listFile=open(listFileName,'w')
#
f=open(inputFile,'r')
while(1):
    line=f.readline()
    #print line
    if(len(line)==0):
        print("Reached end of file")
        break # eof
    line=re.sub(r'#.*$',r'',line).strip()
    #print(">"+str(line)+":"+str(len(line)))
    if(len(line)==0):
        #print "skip"
        continue # comment
    # Remove #....
    if(line.find(r'{')!=-1):
        #
        structs=re.sub(r'{.*$',r'',line).strip()
        if(len(nested)==0 and gotName==False): # first one = struct Name
            structName=structs
            print("Our structure is :"+str(structName))
            writeJsonHead()
            gotName=True
        else:  # else we have structure inside structure
            #outputHeader("struct "+structs+" {")
            nested.append(structs)
            fullPath=".".join(nested)
            fullPath2=".".join(nested)
    elif(line.find(r'}')!=-1):
        if(len(nested)!=0):
            last=nested.pop()
            #outputHeader("};")
        fullPath=".".join(nested)
        fullPath2=".".join(nested)
    elif(line.find(':')!=-1): # varname : type,val,min,max
        if(gotName==False):
            print("No structure name !")
            exit(1)
        line=re.sub(r'#.*$',r'',line)
        line=re.sub(r'//.*$',r'',line)
        # split by :
        (varType,leftOver)=line.split(r':')
        params=leftOver.split(r',')
        for i in range(0,len(params)):
                params[i]=params[i].strip()
                #print "\t"+params[i]+"\n"
        makeStructure(varType,params)
    else:
        print("Invalid line "+str(line))
        exit(1)
f.close()
writeJsonFooter()
jsonFile.close()
listFile.close()
print("All done")
