import argparse
import datetime
import os
import sys
import re
import xml.etree.ElementTree as ET
from collections import OrderedDict
import SCons.Script

def exists(env):
  return True
  
def generate(env):
    env.AddMethod(gen_target_header,"genTargetHeader")
#----------------------------------------------------------------------------
# convert size to hex value
#----------------------------------------------------------------------------
def convSize(n):
    if n[1].lower() == 'x':
        return n
    if n[-1].upper() == "G":
        return hex(int(n[:-1])*1024*1024*1024)
    if n[-1].upper() == "M":
        return hex(int(n[:-1])*1024*1024)
    if n[-1].upper() == "K":
        return hex(int(n[:-1])*1024)
    if n[-1].upper() == "B":
        return hex(int(n[:-1]))
    else:
        raise Exception("Invalid size ".format(n))

#----------------------------------------------------------------------------
# Format name to remove extra spaces and ignore characters in parenthesis
#----------------------------------------------------------------------------
def convName(n):
    #replcase space, backslash and dot with underscore
    n = (n.replace(" ", "_").replace("/", "_")).replace(".","_")
    #ignore charecters in paranthesis
    n = re.sub("[\(\[].*?[\)\]]","",n)
    #replace with single underscore
    while "__" in n:
        for c in n:
            if "__" in n:
                n = n.replace("__","_")
    else:
         return n.upper()

#----------------------------------------------------------------------------
# write from dictionary to file
#----------------------------------------------------------------------------
def writetofile(d, outputdir):
    fp = open(os.path.join(outputdir, 'tzbsp_target_autogen.h'),"wb")
    fp.write("#ifndef TZBSP_TARGET_AUTOGEN_H\n")
    fp.write("#define TZBSP_TARGET_AUTOGEN_H\n")
    fp.write("/**\n")
    fp.write("file tzbsp_target_autogen.h\n")
    fp.write("*/\n")
    fp.write("/*===========================================================================\n")
    fp.write("\t\t\t\ttzbsp_target_autogen file\n  Description: this file is autogenerated from input files extracted from ipcat.")
    fp.write("\n  Copyright (c) 2019 by QUALCOMM Technologies, Incorporated.  All Rights Reserved.\n")
    fp.write("===========================================================================*/\n\n")
    for k in d:
        tofile = "\n#define " + str(k) + "  " + str(d[k])
        fp.write(tofile)
    fp.write("\n\n#endif  //TZBSP_TARGET_AUTOGEN_H")

#----------------------------------------------------------------------------
# usage
# Help on how to use this script
#----------------------------------------------------------------------------
def create_arg_parser():
    """"Creates and returns the ArgumentParser object."""

    parser = argparse.ArgumentParser(description='targetdef_autogen')
    parser.add_argument('-i','--inputDirectory',
                    help='Path to the input directory.')
    parser.add_argument('-o','--outputDirectory',
                    help='Path to the output directory')
    return parser

def getInOutPaths():
    arg_parser = create_arg_parser()
    try:
        parsed_args = arg_parser.parse_args(sys.argv[1:])
    except:
        arg_parser.print_help()
        sys.exit(0)
    if os.path.exists(parsed_args.inputDirectory):
       indir = parsed_args.inputDirectory
    else:
        print("input path is invalid")
        arg_parser.print_help(sys.stderr)
        sys.exit(0)
    if os.path.exists(parsed_args.outputDirectory):
        outdir = parsed_args.outputDirectory
    else:
        print("output path is invalid")
        arg_parser.print_help(sys.stderr)
        sys.exit(0)
    return indir, outdir

def gen_target_header(env):
    build_root = env.RealPath("${BUILD_ROOT}", posix=False)
    chipset = env["CHIPSET"]
    indir = os.path.join(build_root,'ssg','securemsm','platform','config','cfg',chipset)
    outdir = os.path.join(build_root,'ssg','securemsm','platform','config','inc',chipset)
    if os.path.exists(indir):
       print("input Path exist")
    else:
       raise Exception("input path doesnt exist {}".format(indir))
    if os.path.exists(outdir):
       print("output Path exist")
    else:
       raise Exception("output path doesnt exist {}".format(outdir))            
    bankList = ['PIMEM', 'SYSTEM_IMEM', 'DDR_SPACE']
    regionList = ['XBL_SEC','TZ_STAT', 'SSC_MPU_CFG_SSC_MPU_WRAPPER',
                  'pIMEM Vault','TAGS', 'QTEE', 'Trusted Apps',
                  'PIL_REGION', 'UEFI', "XBL(BOOT)", "SMEM", 'QSEE/TZ']
    dict = OrderedDict()

    for filename in os.listdir(indir):
        if not filename.endswith('.xml'): continue
        fullname = os.path.join(indir, filename)
        tree = ET.parse(fullname)
        root = tree.getroot()
        for Bank in root.iter('Bank'):
            if Bank.get('name') in bankList:
                dict[convName("TZ_" + Bank.get('name')+ "_BASE_ADDR")] = Bank.get('addr')
                dict[convName("TZ_" + Bank.get('name')+ "_SIZE")] = convSize(Bank.get('size'))
        for Region in root.iter('Region'):
            if Region.get('name') in regionList:
                dict[convName("TZ_" + Region.get('name')+ "_BASE_ADDR")] = Region.get('addr')
                dict[convName("TZ_" + Region.get('name')+ "_SIZE")] = convSize(Region.get('size'))
        for MemReg in root.iter('MemReg'):
            if (MemReg.get('name') == "MON_STACK") | (MemReg.get('name') == "MON_UNCACHED_STACK"):
                dict[convName(MemReg.get('name')+ "_SIZE_PER_CPU")] = convSize((MemReg.get('size')))
            else:
                dict[convName(MemReg.get('name')+ "_SIZE")] = convSize((MemReg.get('size')))
        for IntNum in root.iter('IntNum'):
             dict[convName(IntNum.get('name'))] = IntNum.get('number')
             dict[convName(IntNum.get('name')+ "_DESC")] = "\"" + IntNum.get('desc') + "\""                
    writetofile(dict, outdir)
