#!/usr/bin/env python
# Copyright (C) 2017 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 argparse
import os
import subprocess
import re
import sys
import xml.dom.minidom

JRE = '/'.join([
  'org.eclipse.jdt.launching.JRE_CONTAINER',
  'org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType',
  'JavaSE-1.8',
])

opts = argparse.ArgumentParser("Create Eclipse Project")
opts.add_argument('-r', '--root', help='Root directory entry')
opts.add_argument('-n', '--name', help='Project name')
opts.add_argument('-x', '--exclude', action='append', help='Exclude paths')
opts.add_argument('-b', '--batch', action='store_true',
                  dest='batch', help='Bazel batch option')
opts.add_argument('--bazel',
                  help=('name of the bazel executable. Defaults to using'
                        ' bazelisk if found, or bazel if bazelisk is not'
                        ' found.'),
                  action='store', default=None, dest='bazel_exe')
args = opts.parse_args()

if not args.root:
  opts.error('Root option not provided')
  sys.exit(1)

root = args.root
ROOT = os.path.abspath(root)
while not os.path.exists(os.path.join(ROOT, 'WORKSPACE')):
  ROOT = os.path.dirname(ROOT)

batch_option = '--batch' if args.batch else None

def find_bazel():
  if args.bazel_exe:
    try:
      return subprocess.check_output(
        ['which', args.bazel_exe]).strip().decode('UTF-8')
    except subprocess.CalledProcessError:
      print('Bazel command: %s not found' % args.bazel_exe, file=sys.stderr)
      sys.exit(1)
  try:
    return subprocess.check_output(
      ['which', 'bazelisk']).strip().decode('UTF-8')
  except subprocess.CalledProcessError:
    try:
      return subprocess.check_output(
        ['which', 'bazel']).strip().decode('UTF-8')
    except subprocess.CalledProcessError:
      print("Neither bazelisk nor bazel found. Please see"
            " Documentation/dev-bazel for instructions on installing"
            " one of them.")
      sys.exit(1)

bazel_exe = find_bazel()

def _build_bazel_cmd(*args):
  cmd = [bazel_exe]
  if batch_option:
    cmd.append('--batch')
  for arg in args:
    cmd.append(arg)
  return cmd

def retrieve_ext_location():
  return subprocess.check_output(_build_bazel_cmd('info', 'output_base')).strip()

def _query_classpath():
  t = '//tools/eclipse:main_classpath_collect'
  try:
    subprocess.check_call(_build_bazel_cmd('build', t))
  except subprocess.CalledProcessError:
    exit(1)
  name = 'bazel-bin/tools/eclipse/' + t.split(':')[1] + '.runtime_classpath'
  return [line.rstrip('\n') for line in open(name)]

def gen_project(name, root=ROOT):
  p = os.path.join(root, '.project')
  with open(p, 'w') as fd:
    print("""\
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
  <name>%(name)s</name>
  <buildSpec>
    <buildCommand>
      <name>org.eclipse.jdt.core.javabuilder</name>
    </buildCommand>
  </buildSpec>
  <natures>
    <nature>org.eclipse.jdt.core.javanature</nature>
  </natures>
</projectDescription>\
    """ % {"name": name}, file=fd)

def gen_classpath(ext):
  def make_classpath():
    impl = xml.dom.minidom.getDOMImplementation()
    return impl.createDocument(None, 'classpath', None)

  def classpathentry(kind, path, src=None, out=None, exported=None):
    e = doc.createElement('classpathentry')
    e.setAttribute('kind', kind)
    # TODO(davido): Remove this and other exclude BUILD files hack
    # when this Bazel bug is fixed:
    # https://github.com/bazelbuild/bazel/issues/1083
    if kind == 'src':
      e.setAttribute('excluding', '**/BUILD')
    e.setAttribute('path', path)
    if src:
      e.setAttribute('sourcepath', src)
    if out:
      e.setAttribute('output', out)
    if exported:
      e.setAttribute('exported', 'true')
    doc.documentElement.appendChild(e)

  doc = make_classpath()
  src = set()
  lib = set()

  java_library = re.compile('bazel-out/(?:.*)-fastbuild/bin(.*)/[^/]+[.]jar$')
  srcs = re.compile('(.*/external/[^/]+)/jar/(.*)[.]jar')
  for p in _query_classpath():
    m = java_library.match(p)
    if m:
      src.add(m.group(1).lstrip('/'))
    else:
      if ext is not None and p.startswith("external"):
        p = os.path.join(ext, p)
        lib.add(p)

  src_paths = {}
  for s in sorted(src):
    out = None

    if s.startswith('lib/'):
      out = 'eclipse-out/lib'

    p = os.path.join(s, 'java')
    if os.path.exists(p):
      classpathentry('src', p, out=out)
      continue

    for env in ['main', 'test', 'java', 'javatests']:
      o = None
      if out:
        o = out + '/' + env
      elif env == 'test' or env == 'javatests':
        o = 'eclipse-out/test'

      if s.startswith(env + '/'):
        src_paths[env] = o
        continue

      for srctype in ['java', 'resources']:
        p = os.path.join(s, 'src', env, srctype)
        if os.path.exists(p):
          src_paths[p] = o

  for s in src_paths:
    classpathentry('src', s, out=src_paths[s])

  for libs in [lib]:
    for j in sorted(libs):
      if excluded(j):
        continue
      s = None
      m = srcs.match(j)
      if m:
        prefix = m.group(1)
        suffix = m.group(2)
        p = os.path.join(prefix, "src", "%s-src.jar" % suffix)
        if os.path.exists(p):
          s = p
      classpathentry('lib', j, s)

  classpathentry('con', JRE)
  classpathentry('output', 'eclipse-out/classes')

  p = os.path.join(ROOT, '.classpath')
  with open(p, 'w') as fd:
    doc.writexml(fd, addindent='\t', newl='\n', encoding='UTF-8')

def excluded(lib):
  if args.exclude:
    for x in args.exclude:
      if x in lib:
        return True
  return False

try:
  name = args.name if args.name else os.path.basename(ROOT)
  gen_project(name)
  gen_classpath(retrieve_ext_location().decode('utf-8'))

except KeyboardInterrupt:
  print('Interrupted by user', file=sys.stderr)
  exit(1)
