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

import os

from cpp_namespace_environment import CppNamespaceEnvironment
from model import Model, UnixName
from schema_loader import SchemaLoader


def _GenerateFilenames(full_namespace):
  # Try to find the file defining the namespace. Eg. for
  # nameSpace.sub_name_space.Type' the following heuristics looks for:
  # 1. name_space_sub_name_space.json,
  # 2. name_space_sub_name_space.idl,
  # 3. sub_name_space.json,
  # 4. sub_name_space.idl,
  # 5. etc.
  sub_namespaces = full_namespace.split('.')
  filenames = [ ]
  basename = None
  for namespace in reversed(sub_namespaces):
    if basename is not None:
      basename = UnixName(namespace + '.' + basename)
    else:
      basename = UnixName(namespace)
    for ext in ['json', 'idl']:
      filenames.append('%s.%s' % (basename, ext))
  return filenames


class NamespaceResolver(object):
  '''Resolves a type name into the namespace the type belongs to.
  - |root| path to the root directory.
  - |path| path to the directory with the API header files, relative to the
    root.
  - |include_rules| List containing tuples with (path, cpp_namespace_pattern)
    used when searching for types.
  - |cpp_namespace_pattern| Default namespace pattern
  '''
  def __init__(self, root, path, include_rules, cpp_namespace_pattern):
    self._root = root
    self._include_rules = [(path, cpp_namespace_pattern)] + include_rules

  def ResolveNamespace(self, full_namespace):
    '''Returns the model.Namespace object associated with the |full_namespace|,
    or None if one can't be found.
    '''
    filenames = _GenerateFilenames(full_namespace)
    for path, cpp_namespace in self._include_rules:
      cpp_namespace_environment = None
      if cpp_namespace:
        cpp_namespace_environment = CppNamespaceEnvironment(cpp_namespace)
      for filename in reversed(filenames):
        filepath = os.path.join(path, filename);
        if os.path.exists(os.path.join(self._root, filepath)):
          schema = SchemaLoader(self._root).LoadSchema(filepath)[0]
          return Model().AddNamespace(
              schema,
              filepath,
              environment=cpp_namespace_environment)
    return None

  def ResolveType(self, full_name, default_namespace):
    '''Returns the model.Namespace object where the type with the given
    |full_name| is defined, or None if one can't be found.
    '''
    name_parts = full_name.rsplit('.', 1)
    if len(name_parts) == 1:
      if full_name not in default_namespace.types:
        return None
      return default_namespace
    full_namespace, type_name = full_name.rsplit('.', 1)
    namespace = self.ResolveNamespace(full_namespace)
    if namespace and type_name in namespace.types:
      return namespace
    return None
