#!/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, '..'))
PUB_PATH = os.path.join(DART_ROOT, 'third_party', 'pkg',
                        'pub', 'bin', 'pub.dart')
IGNORE_PATTERNS = shutil.ignore_patterns(
    '*.map',
    '*.concat.js',
    '*.scriptUrls',
    '*.precompiled.js',
    'bower.json',
    'package.json',
    'CustomElements.*',
    'dart_support.*',
    'interop_support.*',
    'HTMLImports.*',
    'MutationObserver.*',
    'ShadowDOM.*',
    'webcomponents.*',
    'webcomponents-lite.js',
    'unittest*',
    '*_buildLogs*',
    '*.log',
    '*~')

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

# 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)
    return e.returncode

def CreateTimestampFile(options):
  if options.stamp != '':
    dir_name = os.path.dirname(options.stamp)
    if dir_name != '':
      if not os.path.exists(dir_name):
        os.mkdir(dir_name)
    open(options.stamp, 'w').close()

def BuildArguments():
  result = argparse.ArgumentParser(usage=usage)
  result.add_argument("--dart-executable", help="dart executable", default=None)
  result.add_argument("--pub-executable", help="pub executable", default=None)
  result.add_argument("--directory", help="observatory root", default=None)
  result.add_argument("--command", help="[get, build, deploy]", default=None)
  result.add_argument("--silent", help="silence all output", default=None)
  result.add_argument("--sdk", help="Use prebuilt sdk", default=None)
  result.add_argument("--stamp", help="Write a stamp file", default='')
  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

  # Set a default value for pub_snapshot.
  options.pub_snapshot = None

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

  if options.sdk and utils.CheckedInSdkCheckExecutable():
    # Use the checked in pub executable.
    options.pub_snapshot = os.path.join(utils.CheckedInSdkPath(),
                                        'bin',
                                        'snapshots',
                                        'pub.dart.snapshot');
    try:
      if 0 == RunCommand([utils.CheckedInSdkExecutable(),
                          options.pub_snapshot,
                          '--version'], always_silent=True):
        return True
    except OSError as e:
      pass
  options.pub_snapshot = None

  # We need a dart executable.
  return (options.dart_executable is not None)

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

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 PubCommand function
in the tools/observatory_tool.py script.

"""

def PubCommand(dart_executable,
               pub_executable,
               pub_snapshot,
               command,
               silent):
  if pub_executable is not None:
    executable = [pub_executable]
  elif pub_snapshot is not None:
    executable = [utils.CheckedInSdkExecutable(), pub_snapshot]
  else:
    if not silent:
      DisplayBootstrapWarning()
    executable = [dart_executable, PUB_PATH]
    # Prevent the bootstrap Dart executable from running in regular
    # development flow.
    # REMOVE THE FOLLOWING LINE TO USE the dart_bootstrap binary.
    # return False
  if not silent:
    print >> sys.stderr, ('Running command "%s"') % (executable + command)
  return RunCommand(executable + command)

def Deploy(input_dir, output_dir):
  shutil.rmtree(output_dir)
  shutil.copytree(input_dir, output_dir, ignore=IGNORE_PATTERNS)
  index_file = os.path.join(output_dir, 'web', 'index.html')
  os.utime(index_file, None)
  return 0

def RewritePubSpec(input_path, output_path, search, replace):
  with open(input_path, 'rb') as input_file:
    input_data = input_file.read()
    input_data = input_data.replace(search, replace)
    with open(output_path, 'wb+') as output_file:
      output_file.write(input_data)

def ExecuteCommand(options, args):
  cmd = options.command
  if (cmd == 'get'):
    # Always remove pubspec.lock before running 'pub get'.
    try:
      os.remove('pubspec.lock');
    except OSError as e:
      pass
    return PubCommand(options.dart_executable,
                      options.pub_executable,
                      options.pub_snapshot,
                      ['get', '--offline'],
                      options.silent)
  elif (cmd == 'build'):
    return PubCommand(options.dart_executable,
                      options.pub_executable,
                      options.pub_snapshot,
                      ['build',
                       '-DOBS_VER=' + utils.GetVersion(ignore_svn_revision=True),
                       '--output', args[0]],
                      options.silent)
  elif (cmd == 'deploy'):
    Deploy('build', 'deployed')
  elif (cmd == 'rewrite'):
    RewritePubSpec(args[0], args[1], args[2], args[3])
  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.pub_executable != None):
    options.pub_executable = os.path.abspath(options.pub_executable)
  if (options.pub_snapshot != None):
    options.pub_snapshot = os.path.abspath(options.pub_snapshot)
  if (options.stamp != ''):
    options.stamp = os.path.abspath(options.stamp)
  if len(args) == 1:
    args[0] = os.path.abspath(args[0])
  # Pub must be run from the project's root directory.
  ChangeDirectory(options.directory)
  result = ExecuteCommand(options, args)
  if result == 0:
    CreateTimestampFile(options)
  return result


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