# Copyright 2016 The Bazel Authors. All rights reserved.
#
# 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.
#
# Aspect for e4b, taken from intellij_info.bzl

DEPENDENCY_ATTRIBUTES = [
  "deps",
  "runtime_deps",
]

def struct_omit_none(**kwargs):
    d = {name: kwargs[name] for name in kwargs if kwargs[name] != None}
    return struct(**d)

def artifact_location(file):
  return None if file == None else file.path

def library_artifact(java_output):
  if java_output == None or java_output.class_jar == None:
    return None
  return struct_omit_none(
        jar = artifact_location(java_output.class_jar),
        interface_jar = artifact_location(java_output.ijar),
        source_jar = artifact_location(java_output.source_jar),
  )

def annotation_processing_jars(annotation_processing):
  return struct_omit_none(
        jar = artifact_location(annotation_processing.class_jar),
        source_jar = artifact_location(annotation_processing.source_jar),
  )

def jars_from_output(output):
  """ Collect jars for ide-resolve-files from Java output.
  """
  if output == None:
    return []
  return [jar
          for jar in [output.class_jar, output.ijar, output.source_jar]
          if jar != None and not jar.is_source]

def java_rule_ide_info(target, ctx):
  if hasattr(ctx.rule.attr, "srcs"):
     sources = [artifact_location(file)
                for src in ctx.rule.attr.srcs
                for file in src.files]
  else:
     sources = []

  jars = [library_artifact(output) for output in target.java.outputs.jars]
  ide_resolve_files = set([jar
       for output in target.java.outputs.jars
       for jar in jars_from_output(output)])

  gen_jars = []
  if target.java.annotation_processing and target.java.annotation_processing.enabled:
    gen_jars = [annotation_processing_jars(target.java.annotation_processing)]
    ide_resolve_files = ide_resolve_files | set([ jar
        for jar in [target.java.annotation_processing.class_jar,
                    target.java.annotation_processing.source_jar]
        if jar != None and not jar.is_source])

  return (struct_omit_none(
                 sources = sources,
                 jars = jars,
                 generated_jars = gen_jars
          ),
          ide_resolve_files)


def _aspect_impl(target, ctx):
  kind = ctx.rule.kind
  rule_attrs = ctx.rule.attr

  ide_info_text = set()
  ide_resolve_files = set()
  all_deps = []

  for attr_name in DEPENDENCY_ATTRIBUTES:
    if hasattr(rule_attrs, attr_name):
      deps = getattr(rule_attrs, attr_name)
      if type(deps) == 'list':
        for dep in deps:
          ide_info_text = ide_info_text | dep.intellij_info_files.ide_info_text
          ide_resolve_files = ide_resolve_files | dep.intellij_info_files.ide_resolve_files
        all_deps += [str(dep.label) for dep in deps]

  if hasattr(target, "java"):
    (java_rule_ide_info_struct, java_ide_resolve_files) = java_rule_ide_info(target, ctx)
    info = struct(
        label = str(target.label),
        kind = kind,
        dependencies = all_deps,
        build_file_artifact_location = ctx.build_file_path,
    ) + java_rule_ide_info_struct
    ide_resolve_files = ide_resolve_files | java_ide_resolve_files
    output = ctx.new_file(target.label.name + ".e4b-build.json")
    ctx.file_action(output, info.to_json())
    ide_info_text += set([output])

  return struct(
      output_groups = {
        "ide-info-text" : ide_info_text,
        "ide-resolve" : ide_resolve_files,
      },
      intellij_info_files = struct(
        ide_info_text = ide_info_text,
        ide_resolve_files = ide_resolve_files,
      )
    )

e4b_aspect = aspect(implementation = _aspect_impl,
    attr_aspects = DEPENDENCY_ATTRIBUTES
)
"""Aspect for Eclipse 4 Bazel plugin.

This aspect produces information for IDE integration with Eclipse. This only
produces information for Java targets.

This aspect has two output groups:
  - ide-info-text produces .e4b-build.json files that contains information
    about target dependencies and sources files for the IDE.
  - ide-resolve build the dependencies needed for the build (i.e., artifacts
    generated by Java annotation processors).

An e4b-build.json file is a json blob with the following keys:
```javascript
{
  // Label of the corresponding target
  "label": "//package:target",
  // Kind of the corresponding target, e.g., java_test, java_binary, ...
  "kind": "java_library",
  // List of dependencies of this target
  "dependencies": ["//package1:dep1", "//package2:dep2"],
  "Path, relative to the workspace root, of the build file containing the target.
  "build_file_artifact_location": "package/BUILD",
  // List of sources file, relative to the execroot
  "sources": ["package/Test.java"],
  // List of jars created when building this target.
  "jars": [jar1, jar2],
  // List of jars generated by java annotation processors when building this target.
  "generated_jars": [genjar1, genjar2]
}
```

Jar files structure has the following keys:
```javascript
{
  // Location, relative to the execroot, of the jar file or null
  "jar": "bazel-out/host/package/libtarget.jar",
  // Location, relative to the execroot, of the interface jar file,
  // containing only the interfaces of the target jar or null.
  "interface_jar": "bazel-out/host/package/libtarget.interface-jar",
  // Location, relative to the execroot, of the source jar file,
  // containing the sources used to generate the target jar or null.
  "source_jar": "bazel-out/host/package/libtarget.interface-jar",
}
```
"""
