# 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.


""" Utilities for dealing with builder names. This module obtains its attributes
dynamically from builder_name_schema.json. """


import json
import os


# All of these global variables are filled in by _LoadSchema().

# The full schema.
BUILDER_NAME_SCHEMA = None

# Character which separates parts of a builder name.
BUILDER_NAME_SEP = None

# Builder roles.
BUILDER_ROLE_BUILD = 'Build'
BUILDER_ROLE_BUILDSTATS = 'BuildStats'
BUILDER_ROLE_CALMBENCH = 'Calmbench'
BUILDER_ROLE_HOUSEKEEPER = 'Housekeeper'
BUILDER_ROLE_INFRA = 'Infra'
BUILDER_ROLE_PERF = 'Perf'
BUILDER_ROLE_TEST = 'Test'
BUILDER_ROLE_UPLOAD = 'Upload'
BUILDER_ROLES = (BUILDER_ROLE_BUILD,
                 BUILDER_ROLE_BUILDSTATS,
                 BUILDER_ROLE_CALMBENCH,
                 BUILDER_ROLE_HOUSEKEEPER,
                 BUILDER_ROLE_INFRA,
                 BUILDER_ROLE_PERF,
                 BUILDER_ROLE_TEST,
                 BUILDER_ROLE_UPLOAD)


def _LoadSchema():
  """ Load the builder naming schema from the JSON file. """

  def _UnicodeToStr(obj):
    """ Convert all unicode strings in obj to Python strings. """
    if isinstance(obj, unicode):
      return str(obj)
    elif isinstance(obj, dict):
      return dict(map(_UnicodeToStr, obj.iteritems()))
    elif isinstance(obj, list):
      return list(map(_UnicodeToStr, obj))
    elif isinstance(obj, tuple):
      return tuple(map(_UnicodeToStr, obj))

  builder_name_json_filename = os.path.join(
      os.path.dirname(__file__), 'builder_name_schema.json')
  builder_name_schema_json = json.load(open(builder_name_json_filename))

  global BUILDER_NAME_SCHEMA
  BUILDER_NAME_SCHEMA = _UnicodeToStr(
      builder_name_schema_json['builder_name_schema'])

  global BUILDER_NAME_SEP
  BUILDER_NAME_SEP = _UnicodeToStr(
      builder_name_schema_json['builder_name_sep'])

  # Since the builder roles are dictionary keys, just assert that the global
  # variables above account for all of them.
  assert len(BUILDER_ROLES) == len(BUILDER_NAME_SCHEMA)
  for role in BUILDER_ROLES:
    assert role in BUILDER_NAME_SCHEMA


_LoadSchema()


def MakeBuilderName(**parts):
  for v in parts.itervalues():
    if BUILDER_NAME_SEP in v:
      raise ValueError('Parts cannot contain "%s"' % BUILDER_NAME_SEP)

  rv_parts = []

  def process(depth, parts):
    role_key = 'role'
    if depth != 0:
      role_key = 'sub-role-%d' % depth
    role = parts.get(role_key)
    if not role:
      raise ValueError('Invalid parts; missing key %s' % role_key)
    s = BUILDER_NAME_SCHEMA.get(role)
    if not s:
      raise ValueError('Invalid parts; unknown role %s' % role)
    rv_parts.append(role)
    del parts[role_key]

    for key in s.get('keys', []):
      value = parts.get(key)
      if not value:
        raise ValueError('Invalid parts; missing %s' % key)
      rv_parts.append(value)
      del parts[key]

    recurse_roles = s.get('recurse_roles', [])
    if len(recurse_roles) > 0:
      sub_role_key = 'sub-role-%d' % (depth+1)
      sub_role = parts.get(sub_role_key)
      if not sub_role:
        raise ValueError('Invalid parts; missing %s' % sub_role_key)

      found = False
      for recurse_role in recurse_roles:
        if recurse_role == sub_role:
          found = True
          parts = process(depth+1, parts)
          break
      if not found:
        raise ValueError('Invalid parts; unknown sub-role %s' % sub_role)

    for key in s.get('optional_keys', []):
      if parts.get(key):
        rv_parts.append(parts[key])
        del parts[key]

    if len(parts) > 0:
      raise ValueError('Invalid parts; too many parts: %s' % parts)

    return parts

  process(0, parts)

  return BUILDER_NAME_SEP.join(rv_parts)


def DictForBuilderName(builder_name):
  """Makes a dictionary containing details about the builder from its name."""
  split = builder_name.split(BUILDER_NAME_SEP)

  def pop_front(items):
    try:
      return items.pop(0), items
    except:
      raise ValueError(
          'Invalid builder name: %s (not enough parts)' % builder_name)

  result = {}

  def _parse(depth, role, parts):
    schema = BUILDER_NAME_SCHEMA.get(role)
    if not schema:
      raise ValueError('Invalid builder name: %s' % builder_name)
    if depth == 0:
      result['role'] = role
    else:
      result['sub-role-%d' % depth] = role
    for key in schema.get('keys', []):
      value, parts = pop_front(parts)
      result[key] = value
    for sub_role in schema.get('recurse_roles', []):
      if len(parts) > 0 and sub_role == parts[0]:
        parts = _parse(depth+1, parts[0], parts[1:])
    for key in schema.get('optional_keys', []):
      if parts:
        value, parts = pop_front(parts)
        result[key] = value
    if parts:
      raise ValueError('Invalid builder name: %s' % builder_name)
    return parts

  _parse(0, split[0], split[1:])

  return result
