#!/usr/bin/env python3.8
# Copyright 2019 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

'''
Prints completions for GN build target names.

Reads the GN build targets from //out/default/project_lite.json
(generated by prepare_targets.py) and prints completions that match the search
label.

This can be invoked to generate completions in any shell that supports
completions.

For a description of GN labels, run `fx gn help labels`.
'''

import argparse
import collections
import json
import os
import sys

FUCHSIA_DIR = os.environ['FUCHSIA_DIR']
DEFAULT_PROJECT_FILE = 'project_lite.json'

try:
  DEFAULT_OUT_DIR = os.environ['FUCHSIA_BUILD_DIR']
except KeyError:
  DEFAULT_OUT_DIR = os.path.join(FUCHSIA_DIR, 'out', 'default')

class Completions(object):
  '''Provides shell-like completions for partial GN labels.'''

  def __init__(self, prefix):
    self._prefix = prefix
    def factory():
      return collections.defaultdict(factory)
    self._children = factory()

  def prefix(self):
    return self._prefix

  def insert_label(self, label):
    '''Inserts the `label` into the `completions` dict.

    Args:
      label: A GN label that must start with `self.prefix()`.

    Raises:
      Exception: If `label` does not start with `self.prefix()`.
    '''
    if not label.startswith(self._prefix):
      raise Exception('label "{}" must have the prefix "{}"'.format(
          label, self._prefix))
    children = self._children
    for segment in split_label(label[len(self._prefix):]):
      children = children[segment]

  def list_completions(self):
    '''Yields partial GN label completions truncated at the first ambiguity.

    Eg. for a set of targets:
      ['foo/bar/baz:test',
       'foo/bar/bat/bar:test',
       'foo/bar/bat:bin',
       'foo/bar:test']

    the expected completions are:
      ['foo/bar/baz',
       'foo/bar/bat',
       'foo/bar:test']

    Args:
      completions: The dictionary of completions.

    Yields:
      Partial GN labels that should be suggested as completions.
    '''
    if not self._children:
      return

    label = ''
    children = self._children

    # Descend down the label segments until there is a choice
    # to make. These are the most useful completions.
    while len(children) == 1:
      segment, children = next(iter(children.items()))
      label += segment

    if not children:
      # There is only a single match to suggest.
      yield self._prefix + label

    for segment, _ in children.items():
      yield self._prefix + label + segment


def get_project_subdir():
  '''Returns the current working subdirectory of FUCHSIA_DIR.

  Returns:
    A subdirectory without a leading '/'.

  Raises:
    Exception: if the current working directory is not a subdirectory
        of FUCHSIA_DIR.
  '''
  cwd = os.getcwd()
  if not cwd.startswith(FUCHSIA_DIR):
    raise Exception('current working directory must be in {}'.format(
        FUCHSIA_DIR))
  subdir = cwd[len(FUCHSIA_DIR):]
  if subdir.startswith('/'):
    subdir = subdir[1:]
  return subdir


def list_matching_targets(project_file, prefix):
  '''Yields GN targets in `project_file` that match `prefix`.

  Args:
    project_file: A JSON file which contains a list of GN labels under the
        'targets' key in the root object.
    prefix: The GN label prefix against which to match the list of targets.

  Returns:
    A generator that yields GN targets that match the GN label `prefix`.
  '''
  for target in json.load(project_file)['targets']:
    if target.startswith(prefix):
      yield target


def is_label_relative(label):
  '''Returns True if `label` is relative (starts with '//').'''
  return not label.startswith('//')


def concat_labels(base, leaf):
  '''Concatenates two GN labels, removing extra '/' characters if needed.

  Args:
    base: A relative or absolute GN label which does not include a target
          (:foo).
    leaf: A relative GN label.

  Returns:
    A GN label that is the concatenation of `base` and `leaf`. The label is
    relative or absolute depending on the `base` label.

  Raises:
    Exception: If the `leaf` label is absolute or `base` contains a target
               (:foo).
  '''
  if ':' in base:
    raise Exception('base label cannot contain a target: {}'.format(base))
  if leaf.startswith('/'):
    raise Exception('leaf label cannot be absolute: {}'.format(leaf))
  colon = leaf.startswith(':')
  if colon or not leaf or base.endswith('/'):
    return base + leaf
  return '{}/{}'.format(base, leaf)


def make_label_relative(base, absolute):
  '''Makes `absolute` a GN label relative to `base`.

  Args:
    base: An absolute GN label which does not include a target (:foo).
    absolute: An absolute GN label of which `base` is a prefix.

  Returns:
    A GN label relative to `base` that refers to the same label as `absolute`.
  '''
  relative = absolute[len(base):]
  if relative.startswith('/'):
    relative = relative[1:]
  return relative


def split_label(label):
  '''Splits a potentially partial GN label into segments.

  The segments are meant to be joined without a separator, which makes handling
  certain edge cases easier. Each delimiter ('/', ':') is included in the
  segment that follows it. Eg 'foo/bar:baz' => ['foo', '/bar', ':baz'].

  Absolute GN labels always start with the '//' segment.

  Toolchains are kept together with the target segment.

  Args:
    label: A potentially partial GN label, relative or absolute.

  Returns:
    A list of segments that can be joined without a separator to re-create
    the original label.
  '''
  if not label:
    return ['']

  toolchain = ''
  if label.endswith(')'):
    # This label contains a toolchain, which looks like :baz(//toolchain).
    toolchain_idx = label.rindex('(')
    toolchain = label[toolchain_idx:]
    label = label[0:toolchain_idx]

  leaf = ''
  leaf_idx = label.find(':')
  if leaf_idx >= 0:
    leaf = label[leaf_idx:]
    label = label[0:leaf_idx]
  segments = []
  if label.startswith('//'):
    segments = ['//']
    label = label[2:]
  while True:
    # Always search after the last /.
    idx = label.find('/', 1)
    if idx > 0:
      segments.append(label[0:idx])
      label = label[idx:]
    else:
      if label:
        segments.append(label)
      break
  if leaf:
    segments.append(leaf)
  if toolchain:
    if segments:
      segments[-1] += toolchain
    else:
      segments = [toolchain]
  return segments


def main(args):
  base_label = ''
  prefix = args.search_label
  relative = is_label_relative(args.search_label)
  if relative:
    base_label = '//{}'.format(get_project_subdir())
    prefix = concat_labels(base_label, args.search_label)

  eprint('Base:   {}'.format(base_label))
  eprint('Search: {}'.format(args.search_label))
  eprint('Prefix: {}'.format(prefix))

  completions = Completions(args.search_label)
  with open(os.path.join(args.build_dir, args.project_file)) as fin:
    for target in list_matching_targets(fin, prefix):
      if relative:
        target = make_label_relative(base_label, target)
      completions.insert_label(target)

  for completion in completions.list_completions():
    print(completion)


def eprint(*args, **kwargs):
  print(*args, file=sys.stderr, **kwargs)


if __name__ == '__main__':
  p = argparse.ArgumentParser(description=__doc__)
  p.add_argument('--build_dir', default=DEFAULT_OUT_DIR)
  p.add_argument('--project_file', default=DEFAULT_PROJECT_FILE)
  p.add_argument('search_label', nargs='?', default='')
  try:
    main(p.parse_args())
  except Exception as e:
    eprint('error: {}'.format(e))
    sys.exit(1)
