#!/usr/bin/env python
"""This provides a cpuEnv.sh parser and a utility to parse and replace cpuEnv.sh values with a provided dict"""

import os
import sys
from plex import *
import random
import StringIO

# Here's where we define the lexicon for the parser.
# This is parsing a bunch of bash export commands.

letter = Range("AZaz")
digit = Range("09")
hspace = Any(" \t")
nline = Any("\n")
spchars = Any(".-_:{}+/*$<>")
comma = Str(",")
eqsign = Str("=")
quote = Str('"')
name = Rep1(letter | digit | spchars)
nameinquotes = quote + name + quote
space = Any(" \t\n")
openParan = Str("(")
closeParan = Str(")")
comment = Bol + Str("#") + Rep(AnyBut("\n")) + Str("\n")

fileLexicon = Lexicon([
    (comment,  'comment'),
    (space, IGNORE),
    (Str("export"), Begin("Name")),
    State('Name', [
                    (name, 'name'),
                    (quote, IGNORE),
                    (space, IGNORE),
                    (eqsign, Begin("Value"))
                    ]),
    State('Value', [
                    (name, 'value'),
                    (quote, IGNORE),
                    (hspace, IGNORE),
                    (nline, Begin(''))
                    ]),
    (space, IGNORE)
])

def parseAndReplaceEnvPathsFile(envPathsPath, replaceMap, replaceName):
    '''Parse the envPaths file into a list of tuples that represents the name/value.
    Replace the value of any name that is present in replaceMap with the value from the map.
    Replace the value of any name below replaceName whose value contains the old value of replaceName
    Finally update the specified file with the new set of values
    '''
    tempFilePath = os.path.join(os.path.dirname(envPathsPath), "_tmp_multifacility" + str(int(random.random()*1000000)))
    while os.path.exists(tempFilePath):
        stderr.write("Generating a new name for the temporary file\n")
        tempFilePath = os.path.join(os.path.dirname(envPathsPath), "_tmp_multifacility" + str(int(random.random()*1000000)))

    NVPairs = {}
    replaceEnvPairs = {}
    with open(tempFilePath, 'w') as out:
        with open(envPathsPath, 'r') as f:
            scanner = Scanner(fileLexicon, f, envPathsPath)
            currentName = None
            oldReplaceNameValue = None
            newReplaceNameValue = replaceMap.get(replaceName, None)
            while 1:
                token = scanner.read()
                if token[0] is None:
                    break
                elif token[0] == "comment":
                     out.write(token[1])
                elif token[0] == 'name':
                    currentName = token[1]
                elif token[0] == 'value':
                    if not currentName:
                        sys.stderr.write("Obtained Value without a name" + token[1])
                        continue
                    if currentName == replaceName:
                        oldReplaceNameValue = token[1]
                    if currentName in replaceMap:
                        NVPairs[currentName] = replaceMap[currentName]
                        out.write('export ' + currentName + '=' + replaceMap[currentName] + "\n")
                    else:
                        # Replace subsequent instances of the old value of replaceName with its new value
                        if oldReplaceNameValue and oldReplaceNameValue in token[1]:
                            if newReplaceNameValue and replaceName in replaceMap:
                                newPath = token[1].replace(oldReplaceNameValue, newReplaceNameValue)
                            else:
                                newPath = token[1]
                            replaceEnvPairs[currentName] = newPath
                        else:
                            newPath = token[1]
                        NVPairs[currentName] = newPath
                        out.write('export ' + currentName + '=' + newPath + "\n")
                    currentName = None
                else:
                    sys.stderr.write("Unknown token" + token)
        os.rename(tempFilePath, envPathsPath)
        return NVPairs, replaceEnvPairs

# if __name__ == "__main__":
#     parseAndReplaceEnvPathsFile(sys.argv[1], {'TOP': 'ABC123'})
