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

import os

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)

    idl_path = os.path.relpath(idl_path, self.interfaces_root)
    components = os.path.dirname(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, interface_name):
    """Get the fully qualified name of the generated bindings class."""
    return '%s::%s' % (self.Namespace(interface_name),
                       self.BindingsClass(interface_name))

  def FullClassName(self, interface_name):
    """Get the fully qualified name of the implementation class."""
    components = self.NamespaceComponents(interface_name)
    return '::'.join(components + [interface_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')
    return os.path.relpath(path, os.path.dirname(self.interfaces_root))

  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))
