#!/usr/bin/python
# Copyright (C) 2013 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.
#
# TODO(sop): Remove hack after Buck supports Eclipse

from __future__ import print_function
from optparse import OptionParser
from os import path
from subprocess import Popen, PIPE, CalledProcessError, check_call
from xml.dom import minidom
import re
import sys

MAIN = ['//tools/eclipse:classpath']
GWT = ['//gerrit-gwtui:ui_module']
JRE = '/'.join([
  'org.eclipse.jdt.launching.JRE_CONTAINER',
  'org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType',
  'JavaSE-1.7',
])

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

opts = OptionParser()
opts.add_option('--src', action='store_true')
args, _ = opts.parse_args()

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

def gen_classpath():
  def query_classpath(targets):
    deps = []
    p = Popen(['buck', 'audit', 'classpath'] + targets, stdout=PIPE)
    for line in p.stdout:
      deps.append(line.strip())
    s = p.wait()
    if s != 0:
      exit(s)
    return deps

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

  def classpathentry(kind, path, src=None, out=None):
    e = doc.createElement('classpathentry')
    e.setAttribute('kind', kind)
    e.setAttribute('path', path)
    if src:
      e.setAttribute('sourcepath', src)
    if out:
      e.setAttribute('output', out)
    doc.documentElement.appendChild(e)

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

  java_library = re.compile(r'[^/]+/gen/(.*)/lib__[^/]+__output/[^/]+[.]jar$')
  for p in query_classpath(MAIN):
    if p.endswith('-src.jar'):
      # gwt_module() depends on -src.jar for Java to JavaScript compiles.
      gwt_lib.add(p)
      continue

    if p.startswith('buck-out/gen/lib/gwt/'):
      # gwt_module() depends on huge shaded GWT JARs that import
      # incorrect versions of classes for Gerrit. Collect into
      # a private grouping for later use.
      gwt_lib.add(p)
      continue

    m = java_library.match(p)
    if m:
      src.add(m.group(1))
    else:
      lib.add(p)

  for p in query_classpath(GWT):
    m = java_library.match(p)
    if m:
      gwt_src.add(m.group(1))

  for s in sorted(src):
    out = None

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

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

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

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

  for libs in [lib, gwt_lib]:
    for j in sorted(libs):
      s = None
      if j.endswith('.jar'):
        s = j[:-4] + '-src.jar'
        if not path.exists(s):
          s = None
      classpathentry('lib', j, s)

  for s in sorted(gwt_src):
    p = path.join(ROOT, s, 'src', 'main', 'java')
    classpathentry('lib', p, out='buck-out/eclipse/gwtsrc')

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

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

try:
  if args.src:
    try:
      check_call([path.join(ROOT, 'tools', 'download_all.py'), '--src'])
    except CalledProcessError as err:
      exit(1)

  gen_project()
  gen_classpath()

  try:
    targets = ['//tools:buck.properties'] + MAIN + GWT
    check_call(['buck', 'build'] + targets)
  except CalledProcessError as err:
    exit(1)
except KeyboardInterrupt:
  print('Interrupted by user', file=sys.stderr)
  exit(1)
