#!/usr/bin/env python
# Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
"""Helper for building and deploying Observatory"""

import argparse
import os
import platform
import shutil
import subprocess
import sys
import utils

SCRIPT_DIR = os.path.dirname(sys.argv[0])
DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..'))
DART2JS_PATH = os.path.join(DART_ROOT, 'pkg', 'compiler', 'bin', 'dart2js.dart')
IGNORE_PATTERNS = shutil.ignore_patterns(
    '$sdk',
    '*.concat.js',
    '*.dart',
    '*.log',
    '*.map',
    '*.precompiled.js',
    '*.scriptUrls',
    '*_buildLogs*',
    '*~',
    'CustomElements.*',
    'HTMLImports.*',
    'MutationObserver.*',
    'ShadowDOM.*',
    'bower.json',
    'dart_support.*',
    'interop_support.*',
    'package.json',
    'unittest*',
    'webcomponents-lite.js',
    'webcomponents.*')

usage = """observatory_tool.py [options]"""

def DisplayBootstrapWarning():
  print """\

WARNING: Your system cannot run the checked-in Dart SDK. Using the
bootstrap Dart executable will make debug builds slow.
Please see the Wiki for instructions on replacing the checked-in Dart SDK.

https://github.com/dart-lang/sdk/wiki/The-checked-in-SDK-in-tools

To use the dart_bootstrap binary please update the Build function
in the tools/observatory_tool.py script.

"""

def DisplayFailureMessage():
  print """\

ERROR: Observatory failed to build. What should you do?

1. Revert to a working revision of the Dart VM
2. Contact zra@, rmacnak@, dart-vm-team@
3. File a bug: https://github.com/dart-lang/sdk/issues/new

"""

# Run |command|. If its return code is 0, return 0 and swallow its output.
# If its return code is non-zero, emit its output unless |always_silent| is
# True, and return the return code.
def RunCommand(command, always_silent=False):
  try:
    subprocess.check_output(command,
                            stderr=subprocess.STDOUT)
    return 0
  except subprocess.CalledProcessError as e:
    if not always_silent:
      print ("Command failed: " + ' '.join(command) + "\n" +
              "output: " + e.output)
      DisplayFailureMessage()
    return e.returncode

def BuildArguments():
  result = argparse.ArgumentParser(usage=usage)
  result.add_argument("--dart-executable", help="dart executable", default=None)
  result.add_argument("--dart2js-executable", help="dart2js executable",
                      default=None)
  result.add_argument("--directory", help="observatory root", default=None)
  result.add_argument("--command", help="[build, deploy]", default=None)
  result.add_argument("--silent", help="silence all output", default=None)
  result.add_argument("--sdk", help="Use prebuilt sdk", default=None)
  return result

def ProcessOptions(options, args):
  # Fix broken boolean parsing in argparse, where False ends up being True.
  if (options.silent is not None) and (options.silent == "True"):
    options.silent = True
  elif (options.silent is None) or (options.silent == "False"):
    options.silent = False
  else:
    print "--silent expects 'True' or 'False' argument."
    return False

  if (options.sdk is not None) and (options.sdk == "True"):
    options.sdk = True
  elif (options.sdk is None) or (options.sdk == "False"):
    options.sdk = False
  else:
    print "--sdk expects 'True' or 'False' argument."
    return False

  # Required options.
  if options.command is None or options.directory is None:
    return False

  # If a dart2js execuble was provided, try and use that.
  # TODO(whesse): Drop the dart2js-executable option if it isn't used.
  if options.dart2js_executable is not None:
    try:
      if 0 == RunCommand([options.dart2js_executable, '--version'],
                         always_silent=True):
        return True
    except OSError as e:
      pass
  options.dart2js_executable = None

  # Use the checked in dart2js executable.
  if options.sdk and utils.CheckedInSdkCheckExecutable():
    dart2js_binary = 'dart2js.bat' if utils.IsWindows() else 'dart2js'
    options.dart2js_executable = os.path.join(utils.CheckedInSdkPath(),
                                             'bin',
                                             dart2js_binary)
    try:
      if 0 == RunCommand([options.dart2js_executable, '--version'],
                         always_silent=True):
        return True
    except OSError as e:
      pass
  options.dart2js_executable = None

  # We need a dart executable and will run from source
  return (options.dart_executable is not None)

def ChangeDirectory(directory):
  os.chdir(directory);

# - Copy over the filtered web directory
# - Merge in the .js file
# - Copy over the filtered dependency lib directories
# - Copy over the filtered observatory package
def Deploy(output_dir, web_dir, observatory_lib, js_file, pub_packages_dir):
  shutil.rmtree(output_dir)
  os.makedirs(output_dir)

  output_web_dir = os.path.join(output_dir, 'web')
  shutil.copytree(web_dir, output_web_dir, ignore=IGNORE_PATTERNS)
  os.utime(os.path.join(output_web_dir, 'index.html'), None)

  shutil.copy(js_file, output_web_dir)

  packages_dir = os.path.join(output_web_dir, 'packages')
  os.makedirs(packages_dir)
  for subdir in os.listdir(pub_packages_dir):
    libdir = os.path.join(pub_packages_dir, subdir, 'lib')
    if os.path.isdir(libdir):
      shutil.copytree(libdir, os.path.join(packages_dir, subdir),
                      ignore=IGNORE_PATTERNS)
  shutil.copytree(observatory_lib, os.path.join(packages_dir, 'observatory'),
                  ignore=IGNORE_PATTERNS)

def Build(dart_executable,
          dart2js_executable,
          script_path,
          output_path,
          packages_path,
          silent):
  if dart2js_executable is not None:
    command = [dart2js_executable]
  else:
    if not silent:
      DisplayBootstrapWarning()
    command = [dart_executable, DART2JS_PATH]
  command += ['--no-preview-dart-2']
  command += ['-DOBS_VER=' + utils.GetVersion(no_git_hash=True)]
  command += [script_path, '-o', output_path, '--packages=%s' % packages_path]
  # Add the defaults pub used
  command += ['--minify']
  if not silent:
    print >> sys.stderr, 'Running command "%s"' % command
  return RunCommand(command)

def ExecuteCommand(options, args):
  cmd = options.command
  if (cmd == 'build'):
    return Build(options.dart_executable,
                 options.dart2js_executable,
                 args[0],
                 args[1],
                 args[2],
                 options.silent)
  elif (cmd == 'deploy'):
    Deploy(args[0], args[1], args[2], args[3], args[4])
  else:
    print >> sys.stderr, ('ERROR: command "%s" not supported') % (cmd)
    return -1;

def main():
  # Parse the options.
  parser = BuildArguments()
  (options, args) = parser.parse_known_args()
  if not ProcessOptions(options, args):
    parser.print_help()
    return 1
  # Calculate absolute paths before changing directory.
  if (options.dart_executable != None):
    options.dart_executable = os.path.abspath(options.dart_executable)
  if (options.dart2js_executable != None):
    options.dart2js_executable = os.path.abspath(options.dart2js_executable)
  if len(args) == 1:
    args[0] = os.path.abspath(args[0])
  try:
    # Pub must be run from the project's root directory.
    ChangeDirectory(options.directory)
    return ExecuteCommand(options, args)
  except:
    DisplayFailureMessage()

if __name__ == '__main__':
  sys.exit(main());
