#!/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',
    'main.*',
    'unittest*',
    '*_buildLogs*',
    '*.log',
    '*~')

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

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("--package-root", help="package root", default=None)
  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

  with open(os.devnull, 'wb') as silent_sink:
    # 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 == subprocess.call([options.pub_executable, '--version'],
                                stdout=silent_sink,
                                stderr=silent_sink):
          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 == subprocess.call([utils.CheckedInSdkExecutable(),
                                 options.pub_snapshot,
                                 '--version'],
                                 stdout=silent_sink,
                                 stderr=silent_sink):
          return True
      except OSError as e:
        pass
    options.pub_snapshot = None

    # We need a dart executable and a package root.
    return (options.package_root is not None and
            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,
               pkg_root,
               command,
               silent):
  with open(os.devnull, 'wb') as silent_sink:
    if pub_executable is not None:
      executable = [pub_executable]
    elif pub_snapshot is not None:
      executable = [utils.CheckedInSdkExecutable(), pub_snapshot]
    else:
      DisplayBootstrapWarning()
      executable = [dart_executable, '--package-root=' + pkg_root, 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 subprocess.call(executable + command,
                           stdout=silent_sink if silent else None,
                           stderr=silent_sink if silent else None)

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,
                      options.package_root,
                      ['get', '--offline'],
                      options.silent)
  elif (cmd == 'build'):
    return PubCommand(options.dart_executable,
                      options.pub_executable,
                      options.pub_snapshot,
                      options.package_root,
                      ['build',
                       '-DOBS_VER=' + utils.GetVersion(),
                       '--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.package_root != None):
    options.package_root = os.path.abspath(options.package_root)
  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());
