#!/usr/bin/env python
# Copyright (c) 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import json
import optparse
import os
import re
import sys

if sys.version_info < (2, 6, 0):
  sys.stderr.write("python 2.6 or later is required run this script\n")
  sys.exit(1)

import buildbot_common
import build_projects
import build_version
import easy_template
import parse_dsc

from build_paths import SDK_SRC_DIR, OUT_DIR, SDK_RESOURCE_DIR

sys.path.append(os.path.join(SDK_SRC_DIR, 'tools'))
import getos
import oshelpers


def RemoveBuildCruft(outdir):
  for root, _, files in os.walk(outdir):
    for f in files:
      path = os.path.join(root, f)
      ext = os.path.splitext(path)[1]
      # Remove unwanted files from the package. Also remove manifest.json files
      # (which we usually want). These ones are the manifests of the invidual
      # examples, though, which CWS complains about. The master manifest.json
      # is generated after we call RemoveBuildCruft.
      if (ext in ('.d', '.o') or
          f == 'dir.stamp' or
          f == 'manifest.json' or
          re.search(r'_unstripped_.*?\.nexe', f)):
        buildbot_common.RemoveFile(path)


def StripNexes(outdir, platform, pepperdir):
  for root, _, files in os.walk(outdir):
    for f in files:
      path = os.path.join(root, f)
      m = re.search(r'lib(32|64).*\.so', path)
      arch = None
      if m:
        # System .so file. Must be x86, because ARM doesn't support glibc yet.
        arch = 'x86_' + m.group(1)
      else:
        basename, ext = os.path.splitext(f)
        if ext in ('.nexe', '.so'):
          # We can get the arch from the filename...
          valid_arches = ('x86_64', 'x86_32', 'arm')
          for a in valid_arches:
            if basename.endswith(a):
              arch = a
              break
      if not arch:
        continue

      strip = GetStrip(pepperdir, platform, arch, 'newlib')
      buildbot_common.Run([strip, path])


def GetStrip(pepperdir, platform, arch, toolchain):
  base_arch = {'x86_32': 'x86', 'x86_64': 'x86', 'arm': 'arm'}[arch]
  bin_dir = os.path.join(pepperdir, 'toolchain',
                         '%s_%s_%s' % (platform, base_arch, toolchain), 'bin')
  strip_prefix = {'x86_32': 'i686', 'x86_64': 'x86_64', 'arm': 'arm'}[arch]
  strip_name = '%s-nacl-strip' % strip_prefix
  return os.path.join(bin_dir, strip_name)


def main(args):
  parser = optparse.OptionParser()
  parser.add_option('-c', '--channel',
      help='Channel to display in the name of the package.')

  # To setup bash completion for this command first install optcomplete
  # and then add this line to your .bashrc:
  #  complete -F _optcomplete build_app.py
  try:
    import optcomplete
    optcomplete.autocomplete(parser)
  except ImportError:
    pass

  options, args = parser.parse_args(args[1:])

  if options.channel:
    if options.channel not in ('Dev', 'Beta'):
      parser.error('Unknown channel: %s' % options.channel)

  toolchains = ['newlib', 'glibc']

  pepper_ver = str(int(build_version.ChromeMajorVersion()))
  pepperdir = os.path.join(OUT_DIR, 'pepper_' + pepper_ver)
  app_dir = os.path.join(OUT_DIR, 'naclsdk_app')
  app_examples_dir = os.path.join(app_dir, 'examples')
  sdk_resources_dir = SDK_RESOURCE_DIR
  platform = getos.GetPlatform()

  buildbot_common.RemoveDir(app_dir)
  buildbot_common.MakeDir(app_dir)

  # Add some dummy directories so build_projects doesn't complain...
  buildbot_common.MakeDir(os.path.join(app_dir, 'tools'))
  buildbot_common.MakeDir(os.path.join(app_dir, 'toolchain'))

  config = 'Release'

  filters = {}
  filters['DISABLE_PACKAGE'] = False
  filters['EXPERIMENTAL'] = False
  filters['TOOLS'] = toolchains
  filters['DEST'] = ['examples/api', 'examples/getting_started',
                     'examples/demo', 'examples/tutorial']
  tree = parse_dsc.LoadProjectTree(SDK_SRC_DIR, include=filters)
  build_projects.UpdateHelpers(app_dir, clobber=True)
  build_projects.UpdateProjects(app_dir, tree, clobber=False,
                                toolchains=toolchains, configs=[config],
                                first_toolchain=True)

  # Collect permissions from each example, and aggregate them.
  def MergeLists(list1, list2):
    return list1 + [x for x in list2 if x not in list1]
  all_permissions = []
  all_socket_permissions = []
  for _, project in parse_dsc.GenerateProjects(tree):
    permissions = project.get('PERMISSIONS', [])
    all_permissions = MergeLists(all_permissions, permissions)
    socket_permissions = project.get('SOCKET_PERMISSIONS', [])
    all_socket_permissions = MergeLists(all_socket_permissions,
                                        socket_permissions)
  if all_socket_permissions:
    all_permissions.append({'socket': all_socket_permissions})
  pretty_permissions = json.dumps(all_permissions, sort_keys=True, indent=4)

  for filename in ['background.js', 'icon128.png']:
    buildbot_common.CopyFile(os.path.join(sdk_resources_dir, filename),
                             os.path.join(app_examples_dir, filename))

  os.environ['NACL_SDK_ROOT'] = pepperdir

  build_projects.BuildProjects(app_dir, tree, deps=False, clean=False,
                               config=config)

  RemoveBuildCruft(app_dir)
  StripNexes(app_dir, platform, pepperdir)

  # Add manifest.json after RemoveBuildCruft... that function removes the
  # manifest.json files for the individual examples.
  name = 'Native Client SDK'
  if options.channel:
    name += ' (%s)' % options.channel
  template_dict = {
    'name': name,
    'channel': options.channel,
    'description':
        'Native Client SDK examples, showing API use and key concepts.',
    'key': False,  # manifests with "key" are rejected when uploading to CWS.
    'permissions': pretty_permissions,
    'version': build_version.ChromeVersionNoTrunk()
  }
  easy_template.RunTemplateFile(
      os.path.join(sdk_resources_dir, 'manifest.json.template'),
      os.path.join(app_examples_dir, 'manifest.json'),
      template_dict)

  app_zip = os.path.join(app_dir, 'examples.zip')
  os.chdir(app_examples_dir)
  oshelpers.Zip([app_zip, '-r', '*'])

  return 0


if __name__ == '__main__':
  sys.exit(main(sys.argv))
