import sys
sys.dont_write_bytecode = True
import argparse
import fnmatch
import os
import shutil
from distutils.dir_util import copy_tree
from xml.etree import ElementTree as ET

#=========================================================================
# Copy APIs
#-------------------------------------------------------------------------
def copyDynSOmbns(build_flavor, build_root, chipid, meta_modem_pr, platform):
    source       = SEP.join([build_root, 'modem_proc', 'build', 'ms', 'bin', build_flavor, 'so'])
    destination  = SEP.join([meta_modem_pr, 'so'])
    mbnFiles     = []

    for root, dirs, files in os.walk(source, topdown=True):
        mbnFiles = files
        break

    # Remove the foo.mbn since it is only needed for internal tests
    if "foo.mbn" in mbnFiles:
        mbnFiles.remove("foo.mbn")

    if not os.path.exists(destination):
        os.makedirs(destination)

    for soMBN in mbnFiles:
        src = SEP.join([source, soMBN])
        dst = SEP.join([destination, soMBN])
        try:
            shutil.copy(src, dst)
        except Exception as e:
            print ("MCFG Err: Could not copy DynSOmbns \nfrom src: %s\nto dst: %s\n" % (src, dst))
            raiseError(str(e))

def copyMcfgFiles(build_flavor, build_root, chipid, meta_modem_pr, platform, platform_type):
    source          = SEP.join([build_root, 'modem_proc', 'build', 'ms', 'bin', build_flavor, 'configs'])
    destination     = SEP.join([meta_modem_pr, 'mcfg', 'configs'])
    cfgtypes        = ["mcfg_hw", "mcfg_sw"] 
    copyDict        = {}

    for cfgtype in cfgtypes:
        mbnsrc      = SEP.join([source, cfgtype, 'generic'])
        if cfgtype == "mcfg_hw":
            mbnsrc  = getRealPath(SEP.join([mbnsrc, 'common']), chipid)
        mbndst      = SEP.join([destination, cfgtype, (mbnsrc.split(cfgtype)[1]).lstrip(SEP)])

        for root, dirs, files in os.walk(mbnsrc, topdown=True):
            for filename in fnmatch.filter(files, '*.mbn'):
                mbnfilesrc = os.path.join(root, filename)
                mbnfiledst = mbndst + mbnfilesrc.split(mbnsrc)[1]
                copyDict[mbnfilesrc] = mbnfiledst

        autotxtsrc  = getRealPath(SEP.join([source, cfgtype]), platform)
        autotxtdst  = SEP.join([destination, cfgtype])

        for root, dirs, files in os.walk(autotxtsrc, topdown=True):
            for filename in files:
                autotxtfilesrc = os.path.join(root, filename)
                autotxtfiledst = autotxtdst + SEP
                copyDict[autotxtfilesrc] = autotxtfiledst
            break

        oemtxtsrc   = source.split("modem_proc")[0] + "modem_proc"
        oemtxtsrc   = getRealPath(SEP.join([oemtxtsrc, "mcfg", "configs", cfgtype]), platform)
        oemtxtdst   = SEP.join([destination, cfgtype])

        for root, dirs, files in os.walk(oemtxtsrc, topdown=True):
            for filename in files:
                oemtxtfilesrc = os.path.join(root, filename)
                oemtxtfiledst = oemtxtdst + SEP
                copyDict[oemtxtfilesrc] = oemtxtfiledst
            break
        
    for src in copyDict:
        dst = copyDict[src]
        
        if len(src) > WIN_PATH_LEN and MACHINE_OS.lower().startswith('win'):
            src = WIN_LONG_PATH + src.replace("/", "\\")

        try:
            if not os.path.exists(os.path.dirname(dst)):
                os.makedirs(os.path.dirname(dst))
                
            shutil.copy(src, dst)
        except Exception as e:
            print ("MCFG Err: Could not copy MCFG files \nfrom src: %s\nto dst: %s\n" % (src, dst))
            raiseError(str(e))

#=========================================================================
# Helper Functions
#-------------------------------------------------------------------------
def raiseError(errmsg):
    raise Exception(errmsg)

def printEnv():
    print ("MCFG Info: BUILD_FLAVOR: %s" % (BUILD_FLAVOR))
    print ("MCFG Info: BUILD_ROOT: %s" % (BUILD_ROOT))
    print ("MCFG Info: CHIPID: %s" % (CHIPID))
    print ("MCFG Info: PLATFORM: %s" % (PLATFORM))
    print ("MCFG Info: PLATFORM_TYPE: %s" % (PLATFORM_TYPE))

def getRealPath(sourceDir, childDir):
    for root, dirs, files in os.walk(sourceDir):
        for dirname in dirs:
            if childDir.lower() == dirname.lower():
                srcDir = SEP.join([sourceDir, dirname])
                return srcDir

    raiseError("child directory %s not found under sourceDir %s" % (childDir, sourceDir))

def getPlatformType(build_flavor):
    print ("MCFG Info: PLATFORM_TYPE not provided! Trying to extract from BUILD_FLAVOR: %s" % str(build_flavor))
    platform_type = STANDALONE
    for tag in FUSION:
        if tag.upper() in build_flavor.upper():
            platform_type = "FUSION"

    return platform_type

def getChipID(build_flavor):
    print ("MCFG Info: CHIPID not provided! Trying to extract from BUILD_FLAVOR: %s" % str(build_flavor))
    return build_flavor.split(".")[0]

def getBuildFlavor(buildRoot):
    print ("MCFG Info: BUILD_FLAVOR not provided! Trying to extract from CONTENTS_XML: %s" % str(CONTENTS_XML))
    meta_lib = SEP.join([META_ROOT] + META_LIB)
    if os.path.exists(meta_lib):
        sys.path.append(meta_lib)
        import meta_lib as metalib

        mi = metalib.meta_info(file_pfn=CONTENTS_XML)
        build_bid_var_list = mi.get_build_bid_var_list('modem')
        if len(build_bid_var_list) == 1:
            for k in build_bid_var_list:
                return build_bid_var_list[k]

    print ("MCFG Info: BUILD_FLAVOR not provided! Trying to extract from BUILD_ROOT: %s" % str(buildRoot))
    build_flavor = buildRoot.split("-")[-2]
    build_flavor = build_flavor.lower().replace("_", ".")
    return build_flavor

def getProductInfo(xmlPath):
    product_info = {}
    try:
        xmlRoot = ET.parse(xmlPath).getroot()
        for child in xmlRoot:
            if child.tag == 'product_info':
                for grandchild in child:
                    product_info[grandchild.tag.upper()] = grandchild.text

        # rename 'WP' platform to 'WD' since the HW mbns and txt files bear the 'WD' tag
        #if product_info['HLOS_TYPE'].upper() == "WP":
        #    product_info['HLOS_TYPE'] = "WD"

        return product_info
    except Exception as e:
        print ("MCFG Err: Could not find xml root in %s" % str(xmlPath))
        raiseError(str(e))

#=========================================================================
# Macros and Inputs
#-------------------------------------------------------------------------
BUILD_FLAVOR    = ""                                                            # MPSS build flavor
BUILD_ROOT      = ""                                                            # path to the root directory for MPSS build
CHIPID          = ""                                                            # chipset name
CONTENTS_XML    = ""                                                            # path to contents.xml in the META build
FUSION          = ["FUSION", "RMTEFS"]                                          # flavor tags for Fusion platform
MACHINE_OS      = sys.platform                                                  # OS of the machine on which META build is compiling
META_LIB        = ["common", "build", "lib", "meta_lib.py"]                     # path to meta_lib.py in the META build
META_MODEM_PR   = ""                                                            # path to 'modem_pr' directory in the META build
META_ROOT       = ""                                                            # path to the root directory for META build
PLATFORM        = ""                                                            # HLOS_TYPE for the mobile device
PLATFORM_TYPE   = ""                                                            # type of platform for the mobile device
PRODUCT_INFO    = {'PRODUCT_NAME':"", 'CHIPID':"", 'HLOS_TYPE':""}              # product info as mentioned in contents.xml in the META build
SEP             = os.sep                                                        # path separator for current OS
STANDALONE      = "STANDALONE"                                                  # flavor tag for Standalone platform
WIN_LONG_PATH   = "\\\\?\\"                                                     # tag to be appended before paths on windows, to support long paths
WIN_PATH_LEN    = 259                                                           # max length for paths allowed in windows

#=========================================================================
# Main
#-------------------------------------------------------------------------
parser = argparse.ArgumentParser(description="mcfg_meta.py",
                                 formatter_class=argparse.RawTextHelpFormatter)

parser.add_argument('-cx', help='path to contents.xml in the META build',
                    dest="CONTENTS_XML", required=True)
parser.add_argument('-mp', help='path to the modem_pr direcotry in the META build',
                    dest="META_MODEM_PR", required=True)
parser.add_argument('-mr', help='path to the root directory for META build',
                    dest="META_ROOT", required=True)
parser.add_argument('-bf', help='MPSS Build Flavor',
                    dest="BUILD_FLAVOR", default='', required=False)
parser.add_argument('-ch', help='chipset name',
                    dest="CHIPID", default='', required=False)
parser.add_argument('-pt', help='type of platform', choices=['STANDALONE', 'FUSION'],
                    dest="PLATFORM_TYPE", default='', required=False)
args            = parser.parse_args()
print ("mcfg_meta.py args[]: %s" % str(args))

BUILD_ROOT      = os.path.realpath(__file__).split("modem_proc")[0].rstrip(SEP)
CONTENTS_XML    = args.CONTENTS_XML
META_MODEM_PR   = args.META_MODEM_PR.rstrip(SEP)
META_ROOT       = args.META_ROOT.rstrip(SEP)

BUILD_FLAVOR    = getBuildFlavor(BUILD_ROOT) if (args.BUILD_FLAVOR.strip() == "") else args.BUILD_FLAVOR.lower().replace("_", ".")
CHIPID          = getChipID(BUILD_FLAVOR) if (args.CHIPID.strip() == "") else args.CHIPID.lower()
PRODUCT_INFO    = getProductInfo(CONTENTS_XML)
PLATFORM        = PRODUCT_INFO['HLOS_TYPE']
PLATFORM_TYPE   = getPlatformType(BUILD_FLAVOR) if (args.PLATFORM_TYPE.strip() == "") else args.PLATFORM_TYPE.upper()
printEnv()


copyMcfgFiles(BUILD_FLAVOR, BUILD_ROOT, CHIPID, META_MODEM_PR, PLATFORM, PLATFORM_TYPE)
copyDynSOmbns(BUILD_FLAVOR, BUILD_ROOT, CHIPID, META_MODEM_PR, PLATFORM)
