# Copyright 2017 The Cobalt Authors. 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.
"""Helper class for getting names and paths related to interfaces."""

import os

from cobalt.bindings.name_conversion import convert_to_cobalt_name
from cobalt.build.path_conversion import ConvertPath


def _NormalizeSlashes(path):
  if os.path.sep == '\\':
    return path.replace('\\', '/')
  else:
    return path


class PathBuilder(object):
  """Provides helper functions for getting paths related to an interface."""

  def __init__(self, engine_prefix, info_provider, interfaces_root,
               generated_root_directory):
    self.interfaces_root = _NormalizeSlashes(interfaces_root)
    self.generated_root = _NormalizeSlashes(generated_root_directory)
    self.engine_prefix = engine_prefix
    self.info_provider = info_provider
    self.interfaces_info = info_provider.interfaces_info

  @property
  def generated_conversion_header_path(self):
    return os.path.join(self.generated_root,
                        '%s_gen_type_conversion.h' % self.engine_prefix)

  @property
  def generated_conversion_include_path(self):
    return os.path.relpath(self.generated_conversion_header_path,
                           self.generated_root)

  def NamespaceComponents(self, interface_name):
    """Get the interface's namespace as a list of namespace components."""

    # Get the IDL filename relative to the cobalt directory, and split the
    # directory to get the list of namespace components.
    if interface_name in self.interfaces_info:
      interface_info = self.interfaces_info[interface_name]
      idl_path = interface_info['full_path']
    elif interface_name in self.info_provider.enumerations:
      enum_info = self.info_provider.enumerations[interface_name]
      idl_path = enum_info['full_path']
    else:
      raise KeyError('Unknown interface name %s' % interface_name)

    rel_idl_path = os.path.relpath(idl_path, self.interfaces_root)
    components = os.path.dirname(rel_idl_path).split(os.sep)
    return [os.path.basename(self.interfaces_root)] + components

  def Namespace(self, interface_name):
    """Get the interface's namespace."""
    return '::'.join(self.NamespaceComponents(interface_name))

  def BindingsClass(self, interface_name):
    """Get the name of the generated bindings class."""
    return self.engine_prefix.capitalize() + interface_name

  def FullBindingsClassName(self, impl_name, interface_name):
    """Get the fully qualified name of the generated bindings class."""
    return '%s::%s' % (self.Namespace(interface_name),
                       self.BindingsClass(impl_name))

  def FullClassName(self, impl_name, interface_name=None):
    """Get the fully qualified name of the implementation class."""
    interface_name = interface_name or impl_name
    components = self.NamespaceComponents(interface_name)
    return '::'.join(components + [impl_name])

  def ImplementationHeaderPath(self, interface_name):
    """Get an #include path to the interface's implementation .h file."""
    interface_info = self.interfaces_info[interface_name]
    path = ConvertPath(
        interface_info['full_path'], forward_slashes=True, output_extension='h')
    dirname = os.path.dirname(
        os.path.relpath(path, os.path.dirname(self.interfaces_root)))
    name = convert_to_cobalt_name(
        interface_info.get('implemented_as') or interface_name)
    return dirname + '/' + name + '.h'

  def BindingsHeaderIncludePath(self, interface_name):
    """Get an #include path to the interface's generated .h file."""
    path = self.BindingsHeaderFullPath(interface_name)
    return os.path.relpath(path, self.generated_root)

  def BindingsHeaderFullPath(self, interface_name):
    """Get the full path to the interface's implementation .h file."""
    interface_info = self.interfaces_info[interface_name]
    return ConvertPath(
        interface_info['full_path'],
        forward_slashes=True,
        output_directory=self.generated_root,
        output_prefix='%s_' % self.engine_prefix,
        output_extension='h',
        base_directory=os.path.dirname(self.interfaces_root))

  def BindingsImplementationPath(self, interface_name):
    """Get the full path to the interface's implementation .cc file."""
    interface_info = self.interfaces_info[interface_name]
    return ConvertPath(
        interface_info['full_path'],
        forward_slashes=True,
        output_directory=self.generated_root,
        output_prefix='%s_' % self.engine_prefix,
        output_extension='cc',
        base_directory=os.path.dirname(self.interfaces_root))

  def DictionaryHeaderIncludePath(self, dictionary_name):
    """Get the #include path to the dictionary's header."""
    path = self.DictionaryHeaderFullPath(dictionary_name)
    return os.path.relpath(path, self.generated_root)

  def DictionaryHeaderFullPath(self, dictionary_name):
    """Get the full path to the dictionary's generated implementation header."""
    interface_info = self.interfaces_info[dictionary_name]
    return ConvertPath(
        interface_info['full_path'],
        forward_slashes=True,
        output_directory=self.generated_root,
        output_extension='h',
        base_directory=os.path.dirname(self.interfaces_root))

  def DictionaryConversionImplementationPath(self, dictionary_name):
    """Get the full path to the dictionary's conversion header."""
    interface_info = self.interfaces_info[dictionary_name]
    return ConvertPath(
        interface_info['full_path'],
        forward_slashes=True,
        output_directory=self.generated_root,
        output_prefix='%s_' % self.engine_prefix,
        output_extension='cc',
        base_directory=os.path.dirname(self.interfaces_root))

  def EnumHeaderIncludePath(self, enum_name):
    """Get the #include path to the dictionary's header."""
    path = self.EnumHeaderFullPath(enum_name)
    return os.path.relpath(path, self.generated_root)

  def EnumHeaderFullPath(self, enum_name):
    """Get the full path to the dictionary's generated implementation header."""
    interface_info = self.info_provider.enumerations[enum_name]
    return ConvertPath(
        interface_info['full_path'],
        forward_slashes=True,
        output_directory=self.generated_root,
        output_extension='h',
        base_directory=os.path.dirname(self.interfaces_root))

  def EnumConversionImplementationFullPath(self, enum_name):
    """Get the full path to the dictionary's conversion header."""
    interface_info = self.info_provider.enumerations[enum_name]
    return ConvertPath(
        interface_info['full_path'],
        forward_slashes=True,
        output_directory=self.generated_root,
        output_prefix='%s_' % self.engine_prefix,
        output_extension='cc',
        base_directory=os.path.dirname(self.interfaces_root))
