#!/usr/bin/python3
#
# 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.

"""
Generate java test files for test 966.
"""

import generate_smali as base
import os
import sys
from pathlib import Path

BUILD_TOP = os.getenv("ANDROID_BUILD_TOP")
if BUILD_TOP is None:
  print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr)
  sys.exit(1)

# Allow us to import mixins.
sys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python"))

import testgen.mixins as mixins
import functools
import operator
import subprocess

class JavaConverter(mixins.DumpMixin, mixins.Named, mixins.JavaFileMixin):
  """
  A class that can convert a SmaliFile to a JavaFile.
  """
  def __init__(self, inner):
    self.inner = inner

  def get_name(self):
    """Gets the name of this file."""
    return self.inner.get_name()

  def __str__(self):
    out = ""
    for line in str(self.inner).splitlines(keepends = True):
      if line.startswith("#"):
        out += line[1:]
    return out

class Compiler:
  def __init__(self, sources, javac, temp_dir, classes_dir):
    self.javac = javac
    self.temp_dir = temp_dir
    self.classes_dir = classes_dir
    self.sources = sources

  def compile_files(self, args, files):
    """
    Compile the files given with the arguments given.
    """
    args = args.split()
    files = list(map(str, files))
    cmd = ['sh', '-a', '-e', '--', str(self.javac)] + args + sorted(files)
    subprocess.check_call(cmd)
    print("Compiled {} files".format(len(files)))

  def execute(self):
    """
    Compiles this test, doing partial compilation as necessary.
    """
    # Compile Main and all classes first. Force all interfaces to be default so that there will be
    # no compiler problems (works since classes only implement 1 interface).
    for f in self.sources:
      if isinstance(f, base.TestInterface):
        JavaConverter(f.get_specific_version(base.InterfaceType.default)).dump(self.temp_dir)
      else:
        JavaConverter(f).dump(self.temp_dir)
    self.compile_files("-d {}".format(self.classes_dir), self.temp_dir.glob("*.java"))

    # Now we compile the interfaces
    ifaces = set(i for i in self.sources if isinstance(i, base.TestInterface))
    while len(ifaces) != 0:
      # Find those ifaces where there are no (uncompiled) interfaces that are subtypes.
      tops = set(filter(lambda a: not any(map(lambda i: a in i.get_super_types(), ifaces)), ifaces))
      files = []
      # Dump these ones, they are getting compiled.
      for f in tops:
        out = JavaConverter(f)
        out.dump(self.temp_dir)
        files.append(self.temp_dir / out.get_file_name())
      # Force all superinterfaces of these to be empty so there will be no conflicts
      overrides = functools.reduce(operator.or_, map(lambda i: i.get_super_types(), tops), set())
      for overridden in overrides:
        out = JavaConverter(overridden.get_specific_version(base.InterfaceType.empty))
        out.dump(self.temp_dir)
        files.append(self.temp_dir / out.get_file_name())
      self.compile_files("-d {outdir} -cp {outdir}".format(outdir = self.classes_dir), files)
      # Remove these from the set of interfaces to be compiled.
      ifaces -= tops
    print("Finished compiling all files.")
    return

def main(argv):
  javac_exec = Path(argv[1])
  if not javac_exec.exists() or not javac_exec.is_file():
    print("{} is not a shell script".format(javac_exec), file=sys.stderr)
    sys.exit(1)
  temp_dir = Path(argv[2])
  if not temp_dir.exists() or not temp_dir.is_dir():
    print("{} is not a valid source dir".format(temp_dir), file=sys.stderr)
    sys.exit(1)
  classes_dir = Path(argv[3])
  if not classes_dir.exists() or not classes_dir.is_dir():
    print("{} is not a valid classes directory".format(classes_dir), file=sys.stderr)
    sys.exit(1)
  expected_txt = Path(argv[4])
  mainclass, all_files = base.create_all_test_files()

  with expected_txt.open('w') as out:
    print(mainclass.get_expected(), file=out)
  print("Wrote expected output")

  Compiler(all_files, javac_exec, temp_dir, classes_dir).execute()

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