# Copyright 2015 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Configures devil for use in chromium."""

import os
import sys

from pylib import constants
from pylib.constants import host_paths

if host_paths.DEVIL_PATH not in sys.path:
    sys.path.insert(1, host_paths.DEVIL_PATH)

from devil import devil_env
from devil.android.ndk import abis

_BUILD_DIR = os.path.join(constants.DIR_SOURCE_ROOT, 'build')
if _BUILD_DIR not in sys.path:
    sys.path.insert(1, _BUILD_DIR)

import gn_helpers

_DEVIL_CONFIG = os.path.abspath(
    os.path.join(os.path.dirname(__file__), 'devil_chromium.json')
)

_DEVIL_BUILD_PRODUCT_DEPS = {
    'devil_util_device': [
        {
            'platform': 'android',
            'arch': abis.ARM,
            'path_components': ['devil_util_dist'],
        },
        {
            'platform': 'android',
            'arch': abis.ARM_64,
            'path_components': ['devil_util_dist'],
        },
        {
            'platform': 'android',
            'arch': abis.X86,
            'path_components': ['devil_util_dist'],
        },
        {
            'platform': 'android',
            'arch': abis.X86_64,
            'path_components': ['devil_util_dist'],
        },
    ],
    'devil_util_host': [
        {
            'platform': 'linux2',
            'arch': 'x86_64',
            'path_components': ['devil_util_host'],
        },
    ],
    'forwarder_device': [
        {
            'platform': 'android',
            'arch': abis.ARM,
            'path_components': ['forwarder_dist'],
        },
        {
            'platform': 'android',
            'arch': abis.ARM_64,
            'path_components': ['forwarder_dist'],
        },
        {
            'platform': 'android',
            'arch': 'mips',
            'path_components': ['forwarder_dist'],
        },
        {
            'platform': 'android',
            'arch': 'mips64',
            'path_components': ['forwarder_dist'],
        },
        {
            'platform': 'android',
            'arch': abis.X86,
            'path_components': ['forwarder_dist'],
        },
        {
            'platform': 'android',
            'arch': abis.X86_64,
            'path_components': ['forwarder_dist'],
        },
    ],
    'forwarder_host': [
        {
            'platform': 'linux2',
            'arch': 'x86_64',
            'path_components': ['host_forwarder'],
        },
    ],
}


def _UseLocalBuildProducts(output_directory, devil_dynamic_config):
    output_directory = os.path.abspath(output_directory)
    devil_dynamic_config['dependencies'] = {
        dep_name: {
            'file_info': {
                '%s_%s' % (dep_config['platform'], dep_config['arch']): {
                    'local_paths': [
                        os.path.join(
                            output_directory, *dep_config['path_components']
                        ),
                    ],
                }
                for dep_config in dep_configs
            }
        }
        for dep_name, dep_configs in _DEVIL_BUILD_PRODUCT_DEPS.items()
    }


def _BuildWithChromium():
    """Returns value of gclient's |build_with_chromium|."""
    gni_path = os.path.join(_BUILD_DIR, 'config', 'gclient_args.gni')
    if not os.path.exists(gni_path):
        return False
    with open(gni_path) as f:
        data = f.read()
    args = gn_helpers.FromGNArgs(data)
    return args.get('build_with_chromium', False)


def Initialize(
    output_directory=None,
    custom_deps=None,
    adb_path=None,
    use_local_devil_tools=False,
):
    """Initializes devil with chromium's binaries and third-party libraries.

    This includes:
      - Libraries:
        - the android SDK ("android_sdk")
      - Build products:
        - host & device forwarder binaries
            ("forwarder_device" and "forwarder_host")
        - host & device devil_util binaries
            ("devil_util_device" and "devil_util_host")

    Args:
      output_directory: An optional path to the output directory. If not set,
        no built dependencies are configured.
      custom_deps: An optional dictionary specifying custom dependencies.
        This should be of the form:

          {
            'dependency_name': {
              'platform': 'path',
              ...
            },
            ...
          }
      adb_path: An optional path to use for the adb binary. If not set, this uses
        the adb binary provided by the Android SDK.
      use_local_devil_tools: Use locally built versions of devil_util,
        forwarder_dist, etc.
    """
    build_with_chromium = _BuildWithChromium()

    devil_dynamic_config = {
        'config_type': 'BaseConfig',
        'dependencies': {},
    }
    if use_local_devil_tools:
        # Non-chromium users of chromium's //build directory fetch build products
        # from google storage rather than use locally built copies. Chromium uses
        # locally-built copies so that changes to the tools can be easily tested.
        _UseLocalBuildProducts(output_directory, devil_dynamic_config)

    if custom_deps:
        devil_dynamic_config['dependencies'].update(custom_deps)
    if adb_path:
        devil_dynamic_config['dependencies'].update(
            {
                'adb': {
                    'file_info': {
                        devil_env.GetPlatform(): {'local_paths': [adb_path]}
                    }
                }
            }
        )

    config_files = [_DEVIL_CONFIG] if build_with_chromium else None
    devil_env.config.Initialize(
        configs=[devil_dynamic_config], config_files=config_files
    )
