#!/usr/bin/env python
#
# Copyright 2017 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.

"""Creates a script to run a Fushsia executable by delegating to
build/fuchsia/(exe|test)_runner.py.
"""

import argparse
import os
import re
import sys


SCRIPT_TEMPLATE = """\
#!/usr/bin/env python
#
# This file was generated by build/fuchsia/create_runner_script.py

import os
import sys

def main():
  script_directory = os.path.dirname(__file__)

  def ResolvePath(path):
    \"\"\"Returns an absolute filepath given a path relative to this script.
    \"\"\"
    return os.path.abspath(os.path.join(script_directory, path))

  runner_path = ResolvePath('{runner_path}')
  runner_args = {runner_args}
  runner_path_args = {runner_path_args}
  for arg, path in runner_path_args:
    runner_args.extend([arg, ResolvePath(path)])

  os.execv(runner_path,
           [runner_path] + runner_args + sys.argv[1:])

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


def MakeDirectory(dir_path):
  try:
    os.makedirs(dir_path)
  except OSError:
    pass


def WriteDepfile(depfile_path, first_gn_output, inputs=None):
  assert depfile_path != first_gn_output
  inputs = inputs or []
  MakeDirectory(os.path.dirname(depfile_path))
  # Ninja does not support multiple outputs in depfiles.
  with open(depfile_path, 'w') as depfile:
    depfile.write(first_gn_output.replace(' ', '\\ '))
    depfile.write(': ')
    depfile.write(' '.join(i.replace(' ', '\\ ') for i in inputs))
    depfile.write('\n')


def main(args):
  parser = argparse.ArgumentParser()
  parser.add_argument('--runner-script',
                      help='Name of the runner script to use.')
  parser.add_argument('--script-output-path',
                      help='Output path for executable script.')
  parser.add_argument('--depfile',
                      help='Path to the depfile. This must be specified as '
                           'the action\'s first output.')
  parser.add_argument('--test-runner-path',
                      help='Path to test_runner.py (optional).')
  group = parser.add_argument_group('Test runner path arguments.')
  group.add_argument('--output-directory')
  group.add_argument('--runtime-deps-path')
  group.add_argument('--exe-name')
  args, runner_args = parser.parse_known_args(args)

  def RelativizePathToScript(path):
    """Returns the path relative to the output script directory."""
    return os.path.relpath(path, os.path.dirname(args.script_output_path))

  runner_path = args.test_runner_path or os.path.join(
      os.path.dirname(__file__), args.runner_script)
  runner_path = RelativizePathToScript(runner_path)

  runner_path_args = []
  runner_path_args.append(
      ('--output-directory', RelativizePathToScript(args.output_directory)))
  runner_path_args.append(
      ('--runtime-deps-path', RelativizePathToScript(args.runtime_deps_path)))
  runner_path_args.append(
      ('--exe-name', RelativizePathToScript(args.exe_name)))

  with open(args.script_output_path, 'w') as script:
    script.write(SCRIPT_TEMPLATE.format(
        runner_path=str(runner_path),
        runner_args=str(runner_args),
        runner_path_args=str(runner_path_args)))

  os.chmod(args.script_output_path, 0750)

  if args.depfile:
    WriteDepfile(args.depfile, args.script_output_path,
                 [__file__])


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