#!/usr/bin/env python3
# Copyright (C) 2016 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 xml.dom.minidom
import re
import sys

MAIN = '//tools/eclipse:classpath'
AUTO_COLLECT = '//tools/eclipse:autovalue_classpath_collect'

def JRE(java_vers = '25'):
    return '/'.join([
        'org.eclipse.jdt.launching.JRE_CONTAINER',
        'org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType',
        "JavaSE-%s" % java_vers,
    ])

# Map of targets to corresponding classpath collector rules
cp_targets = {
    MAIN: '//tools/eclipse:main_classpath_collect',
}

ROOT = os.path.abspath(__file__)
while not os.path.exists(os.path.join(ROOT, 'MODULE.bazel')):
    ROOT = os.path.dirname(ROOT)

opts = argparse.ArgumentParser("Create Eclipse Project")
opts.add_argument('--plugins', help='create eclipse projects for plugins',
                  action='store_true')
opts.add_argument('--name', help='name of the generated project',
                  action='store', default='gerrit', dest='project_name')
opts.add_argument('-b', '--batch', action='store_true',
                  dest='batch', help='Bazel batch option')
opts.add_argument('-j', '--java', action='store',
                  dest='java', help='Java version to use')
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()


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)


batch_option = '--batch' if args.batch else None
custom_java = args.java
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)
    if custom_java:
        cmd.append('--config=java%s' % custom_java)
    cmd.append('--remote_download_outputs=all')
    return cmd


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


def retrieve_exec_root():
    return subprocess.check_output(_build_bazel_cmd('info', 'execution_root')).strip()


def gen_bazel_path(ext_location):
    bazel = subprocess.check_output(['which', bazel_exe]).strip().decode('UTF-8')
    with open(os.path.join(ROOT, ".bazel_path"), 'w') as fd:
        fd.write("output_base=%s\n" % ext_location)
        fd.write("bazel=%s\n" % bazel)
        fd.write("PATH=%s\n" % os.environ["PATH"])


def _query_classpath(target):
    t = cp_targets[target]
    try:
        subprocess.check_call(_build_bazel_cmd('build', t))
    except subprocess.CalledProcessError:
        exit(1)

    base = 'bazel-bin/tools/eclipse/' + t.split(':')[1]

    runtime_name = base + '.runtime_classpath'
    runtime = [line.rstrip('\n') for line in open(runtime_name)]

    sources = []
    sources_name = base + '.source_classpath'
    if os.path.exists(sources_name):
        sources = [line.rstrip('\n') for line in open(sources_name)]

    return runtime, sources


def _normalize_jar_basename(p):
    b = os.path.basename(p)
    for pref in ('processed_', 'header_'):
        if b.startswith(pref):
            b = b[len(pref):]
    if b.endswith('-sources.jar'):
        b = b[:-len('-sources.jar')] + '.jar'
    return b


def _resolve_repo_path(output_base, p):
    if p.startswith("external"):
        return os.path.join(output_base, p)
    return p


def gen_project(name='gerrit', 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_plugin_classpath(root):
    p = os.path.join(root, '.classpath')
    with open(p, 'w') as fd:
        if os.path.exists(os.path.join(root, 'src', 'test', 'java')):
            testpath = """
  <classpathentry excluding="**/BUILD" kind="src" path="src/test/java"\
 out="eclipse-out/test">
    <attributes><attribute name="test" value="true"/></attributes>
  </classpathentry>"""
        else:
            testpath = ""
        print("""\
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
  <classpathentry excluding="**/BUILD" kind="src" path="src/main/java"/>%(testpath)s
  <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
  <classpathentry combineaccessrules="false" kind="src" path="/gerrit"/>
  <classpathentry kind="output" path="eclipse-out/classes"/>
</classpath>""" % {"testpath": testpath}, file=fd)


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

    def import_jgit_sources():
        classpathentry('src', 'modules/jgit/org.eclipse.jgit/src')
        classpathentry('src', 'modules/jgit/org.eclipse.jgit/resources')
        classpathentry('src', 'modules/jgit/org.eclipse.jgit.archive/src',
            excluding='org/eclipse/jgit/archive/FormatActivator.java')
        classpathentry('src', 'modules/jgit/org.eclipse.jgit.archive/resources')
        classpathentry('src', 'modules/jgit/org.eclipse.jgit.junit/src')
        classpathentry('src', 'modules/jgit/org.eclipse.jgit.ssh.apache/src')
        classpathentry('src', 'modules/jgit/org.eclipse.jgit.ssh.apache/resources')

    def import_prettify_sources():
        classpathentry('src', 'modules/java-prettify/src')

    def classpathentry(kind, path, src=None, out=None, exported=None, excluding=None):
        e = doc.createElement('classpathentry')
        e.setAttribute('kind', kind)
        # Excluding the BUILD file, to avoid the Eclipse warnings:
        # "The resource is a duplicate of ..."
        if kind == 'src':
            e.setAttribute('excluding', '**/BUILD' if not excluding else excluding)
        e.setAttribute('path', path)
        if src:
            e.setAttribute('sourcepath', src)
        if out:
            e.setAttribute('output', out)
        if exported:
            e.setAttribute('exported', 'true')
        atts = None
        if out and "test" in out:
            atts = doc.createElement('attributes')
            testAtt = doc.createElement('attribute')
            testAtt.setAttribute('name', 'test')
            testAtt.setAttribute('value', 'true')
            atts.appendChild(testAtt)
        if "apt_generated" in path or "modules/jgit" in path:
            if not atts:
                atts = doc.createElement('attributes')
            ignoreOptionalProblems = doc.createElement('attribute')
            ignoreOptionalProblems.setAttribute('name', 'ignore_optional_problems')
            ignoreOptionalProblems.setAttribute('value', 'true')
            atts.appendChild(ignoreOptionalProblems)
            optional = doc.createElement('attribute')
            optional.setAttribute('name', 'optional')
            optional.setAttribute('value', 'true')
            atts.appendChild(optional)
        if atts:
            e.appendChild(atts)
        doc.documentElement.appendChild(e)

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

    # Classpath entries are absolute for cross-cell support
    java_library = re.compile('bazel-out/.*?-fastbuild/bin/(.*)/[^/]+[.]jar$')
    proto_library = re.compile('bazel-out/.*?-fastbuild/bin/(.*)proto/(.*)_proto-speed[.]jar$')

    runtime_cp, source_cp = _query_classpath(MAIN)

    source_by_basename = {}
    for p in source_cp:
        source_by_basename[_normalize_jar_basename(p)] = p

    generated_jgit_sources = {
        "org.eclipse.jgit.http.server.ee8/libjgit-servlet-ee8.jar":
            "org.eclipse.jgit.http.server.ee8/jgit-http-server-ee8-srcs.srcjar",
        "org.eclipse.jgit.lfs.server.ee8/libjgit-lfs-server-ee8.jar":
            "org.eclipse.jgit.lfs.server.ee8/jgit-lfs-server-ee8-srcs.srcjar",
    }

    def generated_jgit_source(jar):
        for jar_suffix, src_suffix in generated_jgit_sources.items():
            if jar.endswith(jar_suffix):
                candidate = jar[:-len(jar_suffix)] + src_suffix
                if os.path.exists(candidate):
                    return candidate
        return None

    for p in runtime_cp:
        if p.endswith('-src.jar'):
            continue

        m = java_library.match(p)
        if m and "/external/" not in p:
            src.add(m.group(1))
            # Exceptions: both source and lib
            if p.endswith('libquery_parser.jar') or \
               p.endswith('libgerrit-prolog-common.jar') or \
               p.endswith('external/com_google_protobuf/java/core/libcore.jar') or \
               p.endswith('external/com_google_protobuf/java/core/liblite.jar'):
                lib.add(p)
            if proto_library.match(p) :
                proto.add(p)
        else:
            # Don't mess up with Bazel internal test runner dependencies.
            # When we use Eclipse we rely on it for running the tests
            if p.endswith(
               "external/bazel_tools/tools/jdk/TestRunner_deploy.jar"):
                continue
            p = _resolve_repo_path(output_base, p)
            lib.add(p)

    classpathentry('src', 'java')
    classpathentry('src', 'javatests', out='eclipse-out/test')
    classpathentry('src', 'resources')
    import_jgit_sources()
    import_prettify_sources()
    for s in sorted(src):
        out = None

        if s.startswith('lib/'):
            out = 'eclipse-out/lib'
        elif s.startswith('plugins/'):
            if args.plugins:
                plugins.add(s)
                continue
            out = 'eclipse-out/' + s

        p = os.path.join(s, 'java')
        if os.path.exists(p):
            classpathentry('src', p, out=out + '/main')
            p = os.path.join(s, 'javatests')
            if os.path.exists(p):
                classpathentry('src', p, out=out + '/test')
            continue

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

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

    for libs in [lib]:
        for j in sorted(libs):
            j = _prefer_unprocessed_jar("", j)

            # Some rules_jvm_external entries can be listed as processed_* jars
            # that are not materialized locally. Eclipse treats them as missing
            # required libraries. Skip such entries rather than generating a
            # broken .classpath.
            if (os.path.basename(j).startswith("processed_") or
                os.path.basename(j).startswith("header_")) and not os.path.exists(j):
                continue

            # java-prettify is vendored in-tree under modules/java-prettify.
            # Eclipse compiles it directly from sources, so ignore the external
            # libjava-prettify.jar entry produced by Bazel.
            if os.path.basename(j) == "libjava-prettify.jar" and "/external/" in j:
                continue

            s = generated_jgit_source(j)

            # Attach sources using the classpath_collector output from rules_jvm_external.
            # This replaces the previous heuristic-based source lookup.
            key = _normalize_jar_basename(j)
            if not s and key in source_by_basename:
                sp = _resolve_repo_path(output_base, source_by_basename[key])
                s = sp

            if args.plugins:
                classpathentry('lib', j, s, exported=True)
            else:
                classpathentry('lib', j, s)

    for p in sorted(proto):
        s = p.replace('/proto/lib', '/proto/')
        s = s.replace('/proto/testing/lib', '/proto/testing/')
        s = s.replace('.jar', '-src.jar')
        classpathentry('lib', p, s)

    classpathentry('con', JRE(custom_java) if custom_java else JRE())
    classpathentry('output', 'eclipse-out/classes')
    classpathentry('src', '.apt_generated')
    classpathentry('src', '.apt_generated_tests', out="eclipse-out/test")

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

    if args.plugins:
        for plugin in plugins:
            plugindir = os.path.join(ROOT, plugin)
            try:
                gen_project(plugin.replace('plugins/', ""), plugindir)
                gen_plugin_classpath(plugindir)
            except (IOError, OSError) as err:
                print('error generating project for %s: %s' % (plugin, err),
                      file=sys.stderr)


def _prefer_unprocessed_jar(ext, jar):
    b = os.path.basename(jar)
    if b.startswith('processed_'):
        alt = os.path.join(os.path.dirname(jar), b[len('processed_'):])
    elif b.startswith('header_'):
        alt = os.path.join(os.path.dirname(jar), b[len('header_'):])
    else:
        return jar
    if os.path.exists(os.path.join(ext, alt)):
        return alt
    return jar


def gen_factorypath(exec_root, output_base):
    doc = xml.dom.minidom.getDOMImplementation().createDocument(
        None, 'factorypath', None)

    try:
        subprocess.check_call(_build_bazel_cmd('build', AUTO_COLLECT))
    except subprocess.CalledProcessError:
        exit(1)

    base = 'bazel-bin/tools/eclipse/' + AUTO_COLLECT.split(':')[1]
    processors_name = base + '.processor_classpath'

    processors = []
    if os.path.exists(processors_name):
        processors = [line.rstrip('\n') for line in open(processors_name)]

    for jar in processors:
        jar = _prefer_unprocessed_jar(exec_root, jar)
        jar = _resolve_repo_path(output_base, jar)
        e = doc.createElement('factorypathentry')
        e.setAttribute('kind', 'EXTJAR')
        if os.path.isabs(jar):
            e.setAttribute('id', jar)
        else:
            e.setAttribute('id', os.path.join(exec_root, jar))
        e.setAttribute('enabled', 'true')
        e.setAttribute('runInBatchMode', 'false')
        doc.documentElement.appendChild(e)

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


try:
    output_base = retrieve_ext_location().decode("utf-8")
    exec_root = retrieve_exec_root().decode("utf-8")
    gen_project(args.project_name)
    gen_classpath(exec_root, output_base)
    gen_factorypath(exec_root, output_base)
    gen_bazel_path(output_base)

    try:
        subprocess.check_call(_build_bazel_cmd('build', MAIN))
    except subprocess.CalledProcessError:
        exit(1)
except KeyboardInterrupt:
    print('Interrupted by user', file=sys.stderr)
    exit(1)
