#!/usr/bin/env python
#
# Copyright 2016 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import os
import os.path as path
import generate_protocol_externs
import re
import subprocess
import sys

if len(sys.argv) == 2 and sys.argv[1] == '--help':
  print("Usage: %s" % path.basename(sys.argv[0]))
  sys.exit(0)

java_required_major = 1
java_required_minor = 7

v8_inspector_path = path.dirname(path.dirname(path.abspath(__file__)))

protocol_externs_file = path.join(v8_inspector_path, 'protocol_externs.js')
injected_script_source_name = path.join(v8_inspector_path,
  'injected-script-source.js')
injected_script_externs_file = path.join(v8_inspector_path,
  'injected_script_externs.js')

generate_protocol_externs.generate_protocol_externs(protocol_externs_file,
  path.join(v8_inspector_path, 'js_protocol.json'))

error_warning_regex = re.compile(r'WARNING|ERROR')

closure_compiler_jar = path.join(v8_inspector_path, 'build',
  'closure-compiler', 'closure-compiler.jar')

common_closure_args = [
  '--checks_only',
  '--warning_level', 'VERBOSE'
]

# Error reporting and checking.
errors_found = False

def popen(arguments):
  return subprocess.Popen(arguments, stdout=subprocess.PIPE,
    stderr=subprocess.STDOUT)

def error_excepthook(exctype, value, traceback):
  print 'ERROR:'
  sys.__excepthook__(exctype, value, traceback)
sys.excepthook = error_excepthook

def has_errors(output):
  return re.search(error_warning_regex, output) != None

# Find java. Based on
# http://stackoverflow.com/questions/377017/test-if-executable-exists-in-python.
def which(program):
  def is_exe(fpath):
    return path.isfile(fpath) and os.access(fpath, os.X_OK)

  fpath, fname = path.split(program)
  if fpath:
    if is_exe(program):
      return program
  else:
    for part in os.environ['PATH'].split(os.pathsep):
      part = part.strip('"')
      exe_file = path.join(part, program)
      if is_exe(exe_file):
        return exe_file
  return None

def find_java():
  exec_command = None
  has_server_jvm = True
  java_path = which('java')
  if not java_path:
    java_path = which('java.exe')

  if not java_path:
    print 'NOTE: No Java executable found in $PATH.'
    sys.exit(0)

  is_ok = False
  java_version_out, _ = popen([java_path, '-version']).communicate()
  java_build_regex = re.compile(r'^\w+ version "(\d+)\.(\d+)')
  # pylint: disable=E1103
  match = re.search(java_build_regex, java_version_out)
  if match:
    major = int(match.group(1))
    minor = int(match.group(2))
    is_ok = major >= java_required_major and minor >= java_required_minor
  if is_ok:
    exec_command = [java_path, '-Xms1024m', '-server',
      '-XX:+TieredCompilation']
    check_server_proc = popen(exec_command + ['-version'])
    check_server_proc.communicate()
    if check_server_proc.returncode != 0:
      # Not all Java installs have server JVMs.
      exec_command = exec_command.remove('-server')
      has_server_jvm = False

  if not is_ok:
    print 'NOTE: Java executable version %d.%d or above not found in $PATH.' % (java_required_major, java_required_minor)
    sys.exit(0)
  print 'Java executable: %s%s' % (java_path, '' if has_server_jvm else ' (no server JVM)')
  return exec_command

java_exec = find_java()

spawned_compiler_command = java_exec + [
  '-jar',
  closure_compiler_jar
] + common_closure_args

print 'Compiling injected-script-source.js...'

command = spawned_compiler_command + [
  '--externs', injected_script_externs_file,
  '--externs', protocol_externs_file,
  '--js', injected_script_source_name
]

injected_script_compile_proc = popen(command)

print 'Validating injected-script-source.js...'
injectedscript_check_script_path = path.join(v8_inspector_path, 'build',
  'check_injected_script_source.py')
validate_injected_script_proc = popen([sys.executable,
  injectedscript_check_script_path, injected_script_source_name])

print

(injected_script_compile_out, _) = injected_script_compile_proc.communicate()
print 'injected-script-source.js compilation output:%s' % os.linesep
print injected_script_compile_out
errors_found |= has_errors(injected_script_compile_out)

(validate_injected_script_out, _) = validate_injected_script_proc.communicate()
print 'Validate injected-script-source.js output:%s' % os.linesep
print validate_injected_script_out if validate_injected_script_out else '<empty>'
errors_found |= has_errors(validate_injected_script_out)

os.remove(protocol_externs_file)

if errors_found:
  print 'ERRORS DETECTED'
  sys.exit(1)
