# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Utilities for converting between IDL and Cobalt naming conventions."""

import re

# Matches the boundary between words in CamelCase
# For example, if a space was inserted at the matched boundaries:
#     JSCTestEmptyHTML5Interface -> JSC Test Empty HTML5 Interface
# (?<!^) ensures that we don't match the first character in the string
#     as a word boundary
# (?<![A-Z])(?=[A-Z]) will match an uppercase character that is
#     preceeded by a non-uppercase character: FooBar -> Foo Bar
# (?=[A-Z][a-z]) will match an uppercase character that is followed by
#     a lowercase character: FOOBar -> FOO Bar
titlecase_word_delimiter_re = re.compile(
    '(?<!^)((?<![A-Z])(?=[A-Z])|(?=[A-Z][a-z]))')

# Terms that should always be marked as words regardless of the case of
# neigboring characters.
word_list = ['html']

# Split tokens on non-alphanumeric characters (excluding underscores).
enumeration_value_word_delimeter_re = re.compile(r'[^a-zA-Z0-9]')


def convert_to_cobalt_name(class_name):
  cobalt_name = titlecase_word_delimiter_re.sub('_', class_name).lower()
  for term in word_list:
    replacement = [token for token in
                   re.split('_?(%s)_?' % term, cobalt_name, re.IGNORECASE)
                   if token]
    cobalt_name = '_'.join(replacement)
  return cobalt_name


def capitalize_function_name(operation_name):
  return operation_name[0].capitalize() + operation_name[1:]


def convert_to_cobalt_constant_name(constant_name):
  return 'k' + ''.join(
      (token.capitalize() for token in constant_name.split('_')))


def convert_to_cobalt_enumeration_value(enum_value):
  return 'k' + ''.join((
      token.capitalize()
      for token in enumeration_value_word_delimeter_re.split(
          enum_value)))


def get_interface_name(idl_type):
  """Get the underlying interface name from an idl_type."""
  assert (idl_type.is_interface_type or
          idl_type.is_callback_function or idl_type.is_enum)
  if idl_type.is_nullable:
    return idl_type.inner_type.name
  elif idl_type.name.endswith('ConstructorConstructor'):
    return idl_type.name[0:-len('ConstructorConstructor')]
  elif idl_type.name.endswith('Constructor'):
    return idl_type.constructor_type_name
  else:
    return idl_type.name
