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

"""Build/test configurations, which are just dictionaries. This
"defines" the schema and provides some wrappers."""


import platform
import sys


class Config(object):
  """A Config is basically just a wrapper around a dictionary that species a
  build/test configuration. The dictionary is accessible through the values
  member."""

  # Valid values for target_os (None is also valid):
  OS_ANDROID = "android"
  OS_FNL = "fnl"
  OS_IOS = "ios"
  OS_LINUX = "linux"
  OS_MAC = "mac"
  OS_WINDOWS = "windows"

  # Valid values for target_cpu (None is also valid):
  ARCH_X86 = "x86"
  ARCH_X64 = "x64"
  ARCH_ARM = "arm"
  ARCH_ARM64 = "arm64"

  # Valid values for sanitizer (None is also valid):
  SANITIZER_ASAN = "asan"

  # Standard values for test types (test types are arbitrary strings; other
  # values are allowed).
  TEST_TYPE_DEFAULT = "default"
  TEST_TYPE_UNIT = "unit"
  TEST_TYPE_PERF = "perf"
  TEST_TYPE_INTEGRATION = "integration"

  def __init__(self, target_os=None, target_cpu=None, is_debug=True,
               is_clang=None, sanitizer=None, dcheck_always_on=False,
               is_simulator=False, is_official_build=False, **kwargs):
    """Constructs a Config with key-value pairs specified via keyword arguments.
    If target_os is not specified, it will be set to the host OS."""

    assert target_os in (None, Config.OS_ANDROID, Config.OS_FNL,
                         Config.OS_IOS, Config.OS_LINUX,
                         Config.OS_MAC, Config.OS_WINDOWS)
    assert target_cpu in (None, Config.ARCH_X86, Config.ARCH_X64,
                           Config.ARCH_ARM, Config.ARCH_ARM64)
    assert isinstance(is_debug, bool)
    assert isinstance(is_official_build, bool)
    assert is_clang is None or isinstance(is_clang, bool)
    assert sanitizer in (None, Config.SANITIZER_ASAN)
    if "test_types" in kwargs:
      assert isinstance(kwargs["test_types"], list)

    self.values = {}
    self.values["target_os"] = (self.GetHostOS() if target_os is None else
                                target_os)

    if target_cpu is None:
      if target_os == Config.OS_ANDROID:
        target_cpu = Config.ARCH_ARM
      elif target_os == Config.OS_IOS:
        target_cpu = Config.ARCH_X64 if is_simulator else Config.ARCH_ARM
      else:
        target_cpu = self.GetHostCPUArch()

    self.values["target_cpu"] = target_cpu
    self.values["is_simulator"] = is_simulator
    self.values["is_debug"] = is_debug
    self.values["is_official_build"] = is_official_build
    self.values["is_clang"] = is_clang
    self.values["sanitizer"] = sanitizer
    self.values["dcheck_always_on"] = dcheck_always_on

    self.values.update(kwargs)

  @staticmethod
  def GetHostOS():
    if sys.platform == "linux2":
      return Config.OS_LINUX
    if sys.platform == "darwin":
      return Config.OS_MAC
    if sys.platform == "win32":
      return Config.OS_WINDOWS
    raise NotImplementedError("Unsupported host OS")

  @staticmethod
  def GetHostCPUArch():
    # Derived from //native_client/pynacl/platform.py
    machine = platform.machine()
    if machine in ("x86", "x86-32", "x86_32", "x8632", "i386", "i686", "ia32",
                   "32"):
      return Config.ARCH_X86
    if machine in ("x86-64", "amd64", "x86_64", "x8664", "64"):
      return Config.ARCH_X64
    if machine.startswith("arm"):
      return Config.ARCH_ARM
    raise Exception("Cannot identify CPU arch: %s" % machine)

  # Getters for standard fields ------------------------------------------------

  @property
  def target_os(self):
    """OS of the build/test target."""
    return self.values["target_os"]

  @property
  def target_cpu(self):
    """CPU arch of the build/test target."""
    return self.values["target_cpu"]

  @property
  def is_simulator(self):
    """Is a simulator build?"""
    return self.values["is_simulator"]

  @property
  def is_debug(self):
    """Is Debug build?"""
    return self.values["is_debug"]

  @property
  def is_official_build(self):
    """Is Official build?"""
    return self.values["is_official_build"]

  @property
  def dcheck_always_on(self):
    """DCHECK and MOJO_DCHECK are fatal even in release builds"""
    return self.values["dcheck_always_on"]

  @property
  def is_clang(self):
    """Should use clang?"""
    return self.values["is_clang"]

  @property
  def sanitizer(self):
    """Sanitizer to use, if any."""
    return self.values["sanitizer"]

  @property
  def test_types(self):
    """List of test types to run."""
    return self.values.get("test_types", [Config.TEST_TYPE_DEFAULT])
