# Copyright (c) 2019 Qualcomm Technologies, Inc.
# All Rights Reserved.
# Confidential and Proprietary - Qualcomm Technologies, Inc.

import os
import sys
import SCons

def exists(env):
  return True

def generate(env):
  if sys.platform.startswith("linux"):
    platform = "linux"
    ending = ""
  elif sys.platform.startswith("win"):
    platform = "win"
    ending = ".exe"
  bin_path = os.path.dirname(os.path.realpath(__file__))
  bin_path = os.path.join(bin_path, 'bin', platform)

  minkidl_builder = env.Builder(generator = minkidl_generator,
                                src_suffix = '.idl',
                                suffix = '.h',
                                emitter = minkidl_emitter)

  env['MINKIDL']          = '{}/minkidl{}'.format(bin_path,ending)
  env['MINKIDLCOM']       = '$MINKIDL -o $TARGET $SOURCE '
  env['MINKIDLCOMSTR']    = 'minkidl ${TARGET.basename}.h'
  env.Replace(IDLINCPATH=[])

  env.Append(BUILDERS={'MINKIDL' : minkidl_builder})

  env.AddMethod(run_minkidl,'RunMinkidl')
  ignore_builder = env.Builder(action=ignore_file_builder)
  env.Append(BUILDERS={'IgnoreFileBuilder':ignore_builder})
  if env.StandaloneSdk():
    env.Append(IDLINCPATH='${SDK_ROOT}/inc/idl')
  else:
    env.Append(IDLINCPATH=
               '${BUILD_ROOT}/ssg/securemsm/trustzone/qsee/idl/public')
  try:
    root_env = env['ROOT_GLOBAL_ENV']
    if not root_env.get('MINKIDL_HAS_RUN'):
      env.RunMinkidl()
      root_env['MINKIDL_HAS_RUN'] = True
  except:
    env.RunMinkidl()


def ignore_file_builder(env,target,source):
  with open(str(target[0]),'w+') as f:
    f.write('*.o\n')
    f.write('*.lib\n')
    f.write('*~\n')
    f.write('*.pp\n')
    f.write('*.pyc\n')
    f.write('*.elf\n')
    f.write('*.map\n')
    f.write('*.scl\n')
    f.write('*.mbn\n')
    f.write('*.so\n')
    f.write('*.elf\n')
    f.write('*.pbn\n')
    f.write('*.hash\n')
    f.write('*.dat\n')
    f.write('*.enc\n')
    f.write('*.bin\n')
    f.write('*.efi\n')
    f.write('*.log\n')
    f.write('*.fv\n')
    f.write('*.obj\n')
    f.write('*.tempsym\n')
    f.write('*.i\n')
    f.write('*.scl\n')
    f.write('*.tempscl\n')
    f.write('scorpion/\n')
    f.write('A53_64/\n')
    f.write(env.subst('${BUILD_ID}/') + '\n')
    for idl in sorted(source, key=lambda x: x.get_abspath()):
      rel_path = str(idl).split('trustzone_images')[1]
      if rel_path.startswith('/ssg'):
        rel_path = rel_path.replace('/ssg/','')
        f.write(rel_path + '\n')


def minkidl_generator(env, target, source, for_signature):
  cmds = []
  for t in target:
    cmd = env.subst('$MINKIDLCOM ', target=t, source=source[0])
    incpaths = env.get('IDLINCPATH')
    if incpaths:
      incpaths = [env.RealPath(x) for x in env.Flatten(incpaths)]
      incpathstr = ' -I ' + ' -I '.join(incpaths)
      cmd += incpathstr
    if str(t).endswith('_invoke.h'):
      cmd += ' --skel '
    if str(t).endswith('_invoke.hpp'):
      cmd += ' --skel '
    if str(t).endswith('.hpp'):
      cmd += ' --cpp '
    cmds.append(env.Action(cmd,'minkidl ' + str(t)))
  return cmds

def minkidl_emitter(env, target, source):
    base, ext = os.path.splitext(str(target[0]))
    incl = base + '.h'
    t = [incl]
    incl = base + '.hpp'
    t.append(incl)
    if os.path.basename(str(source[0])).startswith('I'):
      skeleton = base + '_invoke.h'
      t.append(skeleton)
      skeleton = base + '_invoke.hpp'
      t.append(skeleton)
    env.Alias('minkidl_headers',t)
    return (t,source)

def run_minkidl(env,paths=None):
  if paths is None:
    paths = list()
  all_idls = list()

  paths += ['$BUILD_ROOT']
  skips = ['${BUILD_ROOT}/build']

  if not env.StandaloneSdk():
    env = env.Clone()
    env.Tool('deploy_sdk', toolpath=['$BUILD_ROOT/ssg/bsp/build/scripts'])
    # idl files that live under
    # ssg/securemsm/trustzone/qsee/idl/(public/private) are
    # special cases so we skip them
    skips.append(os.path.join('ssg','securemsm','trustzone','qsee','idl'))
  else:
    paths += ['${SDK_ROOT}/inc/idl', '${SDK_ROOT}/samples']

    # Because we do not make TA developers specify what IDL files they
    # depend on and where those IDL files should be compiled out to, we
    # must tell scons how to build all IDL files that TAs may
    # potentially depend on.  This is a headache for a couple reasons:
    # 1) Different construction environments may want to build IDL files
    # with different versions of the IDL compiler.  2) When in the TA SI
    # build system, the BUILD_ROOT folder may have multiple SDK versions
    # underneath it.  So, we will have special behavior for when we are
    # in the TA SI build system to avoid compiling every SDK version's
    # IDL files.
    skips.append('${BUILD_ROOT}/sdk')

  if env.get("QCBUILDDEBUG"):
    print("(idlcompiler.py) Compiling IDL files recursively from here:")
    for p in paths:
      print("                 " + format(env.RealPath(p)))
    print("(idlcompiler.py) Skipping any path found during recursion " +
          "ending with:")
    for s in skips:
      print("                 " + format(env.RealPath(s)))

  for p in paths:
    for dir, subdirs, files in os.walk(env.RealPath(p), topdown=True):
      for skip in skips:
        for subdir in subdirs:
          if (env.subst(os.path.abspath(os.path.join(dir, subdir))) ==
              env.subst(skip)):
            subdirs.remove(subdir)

      for file in files:
        if file.endswith('.idl'):
          all_idls.extend(env.MINKIDL(os.path.join(dir,file)))




  # Here is the special case handling for IDL files under
  # ssg/securemsm/trustzone/qsee/idl/(public|private).  We want the
  # output for these IDLs should go to
  # ssg/securemsm/trustzone/qsee/include.  This behavior is specific
  # to internal QC builds.
  if not env.StandaloneSdk():
    qsee_path = '${BUILD_ROOT}/ssg/securemsm/trustzone/qsee'
    target_dir = os.path.join(qsee_path, 'include')

    idl_files  = env.Glob(qsee_path + '/idl/public/*.idl')
    for idl_file in idl_files:
      idltoh = os.path.basename(os.path.splitext(str(idl_file))[0] + '.h')
      target = os.path.join(target_dir, idltoh)
      all_idls.extend(env.MINKIDL(target=target, source=idl_file))

    idl_files = env.Glob(qsee_path + '/idl/private/*.idl')
    for idl_file in idl_files:
      idltoh = os.path.basename(os.path.splitext(str(idl_file))[0] + '.h')
      target = os.path.join(target_dir, idltoh)
      all_idls.extend(env.MINKIDL(target=target, source=idl_file))

  all_idls = list(set(all_idls))

  if not env.StandaloneSdk():
    ret = env.IgnoreFileBuilder(target='$BUILD_ROOT/ssg/.p4ignore',
                                source=all_idls)
    env.Alias('P4IgnoreFile',ret)
