#!/usr/bin/env python
# Copyright (C) 2015 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import print_function

import atexit
import collections
import json
import hashlib
import optparse
import os
import shutil
import subprocess
import sys
import tempfile

from tools.js import bowerutil

# This script is run with `buck run`, but needs to shell out to buck; this is
# only possible if we avoid buckd.
BUCK_ENV = dict(os.environ)
BUCK_ENV['NO_BUCKD'] = '1'

HEADER = """\
include_defs('//lib/js.defs')

# AUTOGENERATED BY BOWER2BUCK
#
# This file should be merged with an existing BUCK file containing these rules.
#
# This comment SHOULD NOT be copied to the existing BUCK file, and you should
# leave alone any non-bower_component contents of the file.
#
# Generally, the following attributes SHOULD be copied from this file to the
# existing BUCK file:
#  - package: the normalized package name
#  - version: the exact version number
#  - deps: direct dependencies of the package
#  - sha1: a hash of the package contents
#
# The following fields SHOULD NOT be copied to the existing BUCK file:
#  - semver: manually-specified semantic version, not included in autogenerated
#    output.
#
# The following fields require SPECIAL HANDLING:
#  - license: all licenses in this file are specified as TODO. You must replace
#    this text with one of the existing licenses defined in lib/BUCK, or
#    define a new one if necessary. Leave existing licenses alone.

"""


def usage():
  print(('Usage: %s -o <outfile> [//path/to:bower_components_rule...]'
         % sys.argv[0]),
        file=sys.stderr)
  return 1


class Rule(object):
  def __init__(self, bower_json_path):
    with open(bower_json_path) as f:
      bower_json = json.load(f)
    self.name = bower_json['name']
    self.version = bower_json['version']
    self.deps = bower_json.get('dependencies', {})
    self.license = bower_json.get('license', 'NO LICENSE')
    self.sha1 = bowerutil.hash_bower_component(
        hashlib.sha1(), os.path.dirname(bower_json_path)).hexdigest()

  def to_rule(self, packages):
    if self.name not in packages:
      raise ValueError('No package name found for %s' % self.name)

    lines = [
        'bower_component(',
        "  name = '%s'," % self.name,
        "  package = '%s'," % packages[self.name],
        "  version = '%s'," % self.version,
        ]
    if self.deps:
      if len(self.deps) == 1:
        lines.append("  deps = [':%s']," % next(self.deps.iterkeys()))
      else:
        lines.append('  deps = [')
        lines.extend("    ':%s'," % d for d in sorted(self.deps.iterkeys()))
        lines.append('  ],')
    lines.extend([
        "  license = 'TODO: %s'," % self.license,
        "  sha1 = '%s'," % self.sha1,
        ')'])
    return '\n'.join(lines)


def build_bower_json(targets, buck_out):
  """create bower.json so 'bower install' fetches transitive deps"""
  bower_json = collections.OrderedDict()
  bower_json['name'] = 'bower2buck-output'
  bower_json['version'] = '0.0.0'
  bower_json['description'] = 'Auto-generated bower.json for dependency management'
  bower_json['private'] = True
  bower_json['dependencies'] = {}

  deps = subprocess.check_output(
      ['buck', 'query', '-v', '0',
       "filter('__download_bower', deps(%s))" % '+'.join(targets)],
      env=BUCK_ENV)

  # __bower_version contains the version number coming from version
  # attr in BUCK/BUILD
  deps = deps.replace('__download_bower', '__bower_version').split()
  subprocess.check_call(['buck', 'build'] + deps, env=BUCK_ENV)

  for dep in deps:
    dep = dep.replace(':', '/').lstrip('/')
    depout = os.path.basename(dep)
    version_json = os.path.join(buck_out, 'gen', dep, depout)
    with open(version_json) as f:
      bower_json['dependencies'].update(json.load(f))

  tmpdir = tempfile.mkdtemp()
  atexit.register(lambda: shutil.rmtree(tmpdir))
  ret = os.path.join(tmpdir, 'bower.json')
  with open(ret, 'w') as f:
    json.dump(bower_json, f, indent=2)
  return ret


def get_package_name(name, package_version):
  v = package_version.lower()
  if '#' in v:
    return v[:v.find('#')]
  return name


def get_packages(path):
  with open(path) as f:
    bower_json = json.load(f)
  return dict((n, get_package_name(n, v))
              for n, v in bower_json.get('dependencies', {}).iteritems())


def collect_rules(packages):
  # TODO(dborowitz): Use run_npm_binary instead of system bower.
  rules = {}
  subprocess.check_call(['bower', 'install'])
  for dirpath, dirnames, filenames in os.walk('.', topdown=True):
    if '.bower.json' not in filenames:
      continue
    del dirnames[:]
    rule = Rule(os.path.join(dirpath, '.bower.json'))
    rules[rule.name] = rule

    # Oddly, the package name referred to in the deps section of dependents,
    # e.g. 'PolymerElements/iron-ajax', is not found anywhere in this
    # bower.json, which only contains 'iron-ajax'. Build up a map of short name
    # to package name so we can resolve them later.
    # TODO(dborowitz): We can do better:
    #  - Infer 'user/package' from GitHub URLs (i.e. a simple subset of Bower's package
    #    resolution logic).
    #  - Resolve aliases using https://bower.herokuapp.com/packages/shortname
    #    (not currently biting us but it might in the future.)
    for n, v in rule.deps.iteritems():
      p = get_package_name(n, v)
      old = packages.get(n)
      if old is not None and old != p:
        raise ValueError('multiple packages named %s: %s != %s' % (n, p, old))
      packages[n] = p

  return rules


def find_buck_out():
  dir = os.getcwd()
  while not os.path.isfile(os.path.join(dir, '.buckconfig')):
    dir = os.path.dirname(dir)
  return os.path.join(dir, 'buck-out')


def main(args):
  opts = optparse.OptionParser()
  opts.add_option('-o', help='output file location')
  opts, args = opts.parse_args()

  if not opts.o or not all(a.startswith('//') for a in args):
    return usage()
  outfile = os.path.abspath(opts.o)
  buck_out = find_buck_out()

  targets = args if args else ['//polygerrit-ui/...']
  bower_json_path = build_bower_json(targets, buck_out)
  os.chdir(os.path.dirname(bower_json_path))
  packages = get_packages(bower_json_path)
  rules = collect_rules(packages)

  with open(outfile, 'w') as f:
    f.write(HEADER)
    for _, r in sorted(rules.iteritems()):
      f.write('\n\n%s' % r.to_rule(packages))

  print('Wrote bower_components rules to:\n  %s' % outfile)


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