#!/usr/bin/env python
#
# Copyright (c) 2017, 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.

import multiprocessing
import optparse
import os
import subprocess
import sys
import time
import utils

HOST_OS = utils.GuessOS()
HOST_CPUS = utils.GuessCpus()
SCRIPT_DIR = os.path.dirname(sys.argv[0])
DART_ROOT = os.path.realpath(os.path.join(SCRIPT_DIR, '..'))
AVAILABLE_ARCHS = [
    'ia32', 'x64', 'simarm', 'arm', 'simarmv6', 'armv6', 'simarmv5te',
    'armv5te', 'simarm64', 'arm64', 'simdbc', 'simdbc64', 'armsimdbc',
    'armsimdbc64', 'simarm_x64'
]

usage = """\
usage: %%prog [options] [targets]

This script invokes ninja to build Dart.
"""


def BuildOptions():
    result = optparse.OptionParser(usage=usage)
    result.add_option(
        "-a",
        "--arch",
        help='Target architectures (comma-separated).',
        metavar='[all,' + ','.join(AVAILABLE_ARCHS) + ']',
        default=utils.GuessArchitecture())
    result.add_option(
        "-b",
        "--bytecode",
        help='Build with the kernel bytecode interpreter. DEPRECATED.',
        default=False,
        action='store_true')
    result.add_option(
        "-j", type=int, help='Ninja -j option for Goma builds.', default=1000)
    result.add_option(
        "-l", type=int, help='Ninja -l option for Goma builds.', default=64)
    result.add_option(
        "-m",
        "--mode",
        help='Build variants (comma-separated).',
        metavar='[all,debug,release,product]',
        default='debug')
    result.add_option(
        "--no-start-goma",
        help="Don't try to start goma",
        default=False,
        action='store_true')
    result.add_option(
        "--os",
        help='Target OSs (comma-separated).',
        metavar='[all,host,android]',
        default='host')
    result.add_option(
        "-v",
        "--verbose",
        help='Verbose output.',
        default=False,
        action="store_true")
    return result


def ProcessOsOption(os_name):
    if os_name == 'host':
        return HOST_OS
    return os_name


def ProcessOptions(options, args):
    if options.arch == 'all':
        options.arch = 'ia32,x64,simarm,simarm64,simdbc64'
    if options.mode == 'all':
        options.mode = 'debug,release,product'
    if options.os == 'all':
        options.os = 'host,android'
    options.mode = options.mode.split(',')
    options.arch = options.arch.split(',')
    options.os = options.os.split(',')
    for mode in options.mode:
        if not mode in ['debug', 'release', 'product']:
            print("Unknown mode %s" % mode)
            return False
    for arch in options.arch:
        if not arch in AVAILABLE_ARCHS:
            print("Unknown arch %s" % arch)
            return False
    options.os = [ProcessOsOption(os_name) for os_name in options.os]
    for os_name in options.os:
        if not os_name in ['android', 'freebsd', 'linux', 'macos', 'win32']:
            print("Unknown os %s" % os_name)
            return False
        if os_name != HOST_OS:
            if os_name != 'android':
                print("Unsupported target os %s" % os_name)
                return False
            if not HOST_OS in ['linux', 'macos']:
                print("Cross-compilation to %s is not supported on host os %s."
                      % (os_name, HOST_OS))
                return False
            if not arch in [
                    'ia32', 'x64', 'arm', 'armv6', 'armv5te', 'arm64', 'simdbc',
                    'simdbc64'
            ]:
                print(
                    "Cross-compilation to %s is not supported for architecture %s."
                    % (os_name, arch))
                return False
            # We have not yet tweaked the v8 dart build to work with the Android
            # NDK/SDK, so don't try to build it.
            if not args:
                print(
                    "For android builds you must specify a target, such as 'runtime'."
                )
                return False
    return True


def NotifyBuildDone(build_config, success, start):
    if not success:
        print("BUILD FAILED")

    sys.stdout.flush()

    # Display a notification if build time exceeded DART_BUILD_NOTIFICATION_DELAY.
    notification_delay = float(
        os.getenv('DART_BUILD_NOTIFICATION_DELAY', sys.float_info.max))
    if (time.time() - start) < notification_delay:
        return

    if success:
        message = 'Build succeeded.'
    else:
        message = 'Build failed.'
    title = build_config

    command = None
    if HOST_OS == 'macos':
        # Use AppleScript to display a UI non-modal notification.
        script = 'display notification  "%s" with title "%s" sound name "Glass"' % (
            message, title)
        command = "osascript -e '%s' &" % script
    elif HOST_OS == 'linux':
        if success:
            icon = 'dialog-information'
        else:
            icon = 'dialog-error'
        command = "notify-send -i '%s' '%s' '%s' &" % (icon, message, title)
    elif HOST_OS == 'win32':
        if success:
            icon = 'info'
        else:
            icon = 'error'
        command = (
            "powershell -command \""
            "[reflection.assembly]::loadwithpartialname('System.Windows.Forms')"
            "| Out-Null;"
            "[reflection.assembly]::loadwithpartialname('System.Drawing')"
            "| Out-Null;"
            "$n = new-object system.windows.forms.notifyicon;"
            "$n.icon = [system.drawing.systemicons]::information;"
            "$n.visible = $true;"
            "$n.showballoontip(%d, '%s', '%s', "
            "[system.windows.forms.tooltipicon]::%s);\"") % (
                5000,  # Notification stays on for this many milliseconds
                message,
                title,
                icon)

    if command:
        # Ignore return code, if this command fails, it doesn't matter.
        os.system(command)


def GenerateBuildfilesIfNeeded():
    if os.path.exists(utils.GetBuildDir(HOST_OS)):
        return True
    command = [
        'python',
        os.path.join(DART_ROOT, 'tools', 'generate_buildfiles.py')
    ]
    print("Running " + ' '.join(command))
    process = subprocess.Popen(command)
    process.wait()
    if process.returncode != 0:
        print("Tried to generate missing buildfiles, but failed. "
              "Try running manually:\n\t$ " + ' '.join(command))
        return False
    return True


def RunGNIfNeeded(out_dir, target_os, mode, arch):
    if os.path.isfile(os.path.join(out_dir, 'args.gn')):
        return
    gn_os = 'host' if target_os == HOST_OS else target_os
    gn_command = [
        'python',
        os.path.join(DART_ROOT, 'tools', 'gn.py'),
        '-m',
        mode,
        '-a',
        arch,
        '--os',
        gn_os,
        '-v',
    ]
    process = subprocess.Popen(gn_command)
    process.wait()
    if process.returncode != 0:
        print("Tried to run GN, but it failed. Try running it manually: \n\t$ "
              + ' '.join(gn_command))


def UseGoma(out_dir):
    args_gn = os.path.join(out_dir, 'args.gn')
    return 'use_goma = true' in open(args_gn, 'r').read()


# Try to start goma, but don't bail out if we can't. Instead print an error
# message, and let the build fail with its own error messages as well.
goma_started = False


def EnsureGomaStarted(out_dir):
    global goma_started
    if goma_started:
        return True
    args_gn_path = os.path.join(out_dir, 'args.gn')
    goma_dir = None
    with open(args_gn_path, 'r') as fp:
        for line in fp:
            if 'goma_dir' in line:
                words = line.split()
                goma_dir = words[2][1:-1]  # goma_dir = "/path/to/goma"
    if not goma_dir:
        print('Could not find goma for ' + out_dir)
        return False
    if not os.path.exists(goma_dir) or not os.path.isdir(goma_dir):
        print('Could not find goma at ' + goma_dir)
        return False
    goma_ctl = os.path.join(goma_dir, 'goma_ctl.py')
    goma_ctl_command = [
        'python',
        goma_ctl,
        'ensure_start',
    ]
    process = subprocess.Popen(goma_ctl_command)
    process.wait()
    if process.returncode != 0:
        print(
            "Tried to run goma_ctl.py, but it failed. Try running it manually: "
            + "\n\t" + ' '.join(goma_ctl_command))
        return False
    goma_started = True
    return True


# Returns a tuple (build_config, command to run, whether goma is used)
def BuildOneConfig(options, targets, target_os, mode, arch):
    build_config = utils.GetBuildConf(mode, arch, target_os)
    out_dir = utils.GetBuildRoot(HOST_OS, mode, arch, target_os)
    using_goma = False
    # TODO(zra): Remove auto-run of gn, replace with prompt for user to run
    # gn.py manually.
    RunGNIfNeeded(out_dir, target_os, mode, arch)
    command = ['ninja', '-C', out_dir]
    if options.verbose:
        command += ['-v']
    if UseGoma(out_dir):
        if options.no_start_goma or EnsureGomaStarted(out_dir):
            using_goma = True
            command += [('-j%s' % str(options.j))]
            command += [('-l%s' % str(options.l))]
        else:
            # If we couldn't ensure that goma is started, let the build start, but
            # slowly so we can see any helpful error messages that pop out.
            command += ['-j1']
    command += targets
    return (build_config, command, using_goma)


def RunOneBuildCommand(build_config, args):
    start_time = time.time()
    print(' '.join(args))
    process = subprocess.Popen(args, stdin=None)
    process.wait()
    if process.returncode != 0:
        NotifyBuildDone(build_config, success=False, start=start_time)
        return 1
    else:
        NotifyBuildDone(build_config, success=True, start=start_time)

    return 0


def RunOneGomaBuildCommand(args):
    try:
        print(' '.join(args))
        process = subprocess.Popen(args, stdin=None)
        process.wait()
        print(' '.join(args) + " done.")
        return process.returncode
    except KeyboardInterrupt:
        return 1


def Main():
    starttime = time.time()
    # Parse the options.
    parser = BuildOptions()
    (options, args) = parser.parse_args()
    if not ProcessOptions(options, args):
        parser.print_help()
        return 1
    # Determine which targets to build. By default we build the "all" target.
    if len(args) == 0:
        targets = ['all']
    else:
        targets = args

    if not GenerateBuildfilesIfNeeded():
        return 1

    # Build all targets for each requested configuration.
    configs = []
    for target_os in options.os:
        for mode in options.mode:
            for arch in options.arch:
                configs.append(
                    BuildOneConfig(options, targets, target_os, mode, arch))

    # Build regular configs.
    goma_builds = []
    for (build_config, args, goma) in configs:
        if args is None:
            return 1
        if goma:
            goma_builds.append(args)
        elif RunOneBuildCommand(build_config, args) != 0:
            return 1

    # Run goma builds in parallel.
    pool = multiprocessing.Pool(multiprocessing.cpu_count())
    results = pool.map(RunOneGomaBuildCommand, goma_builds, chunksize=1)
    for r in results:
        if r != 0:
            return 1

    endtime = time.time()
    print("The build took %.3f seconds" % (endtime - starttime))
    return 0


if __name__ == '__main__':
    sys.exit(Main())
