# 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,
                        f'{self.engine_prefix}_gen_type_conversion.h')

  @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(f'Unknown interface name {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 f'{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=f'{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=f'{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=f'{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=f'{self.engine_prefix}_',
        output_extension='cc',
        base_directory=os.path.dirname(self.interfaces_root))
