#
# Copyright 2016 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.
#
"""Functionality to enumerate and represent starboard ports."""

import importlib
import os
import sys

if "environment" in sys.modules:
  environment = sys.modules["environment"]
else:
  env_path = os.path.abspath(os.path.dirname(__file__))
  if env_path not in sys.path:
    sys.path.append(env_path)
  environment = importlib.import_module("environment")


import logging
import re


# The list of files that must be present in a directory to allow it to be
# considered a valid port.
_PORT_FILES = [
    'gyp_configuration.gypi',
    'gyp_configuration.py',
    'starboard_platform.gyp',
    'configuration_public.h',
    'atomic_public.h',
    'thread_types_public.h',
]


# Whether to emit warnings if it finds a directory that almost has a port.
# TODO: Enable when tree is clean.
_WARN_ON_ALMOST_PORTS = False


def _IsValidPortFilenameList(directory, filenames):
  """Determines if |filenames| contains the required files for a valid port."""
  missing = set(_PORT_FILES) - set(filenames)
  if missing:
    if len(missing) < (len(_PORT_FILES) / 2) and _WARN_ON_ALMOST_PORTS:
      logging.warning('Directory %s contains several files needed for a port, '
                      'but not all of them. In particular, it is missing: %s',
                      directory, ', '.join(missing))
  return not missing


def _GetPortName(root, directory):
  """Gets the name of a port found at |directory| off of |root|."""

  assert directory.startswith(root)
  start = len(root) + 1  # Remove the trailing slash from the root.

  assert start < len(directory)

  # Calculate the name based on relative path from search root to port.
  return re.sub(r'[^a-zA-Z0-9_]', r'-', directory[start:])


def _GetAllPlatforms(port_root_paths):
  """Retrieves information about all available Cobalt ports.

  Args:
    port_root_paths:  List of paths that will be crawled to find ports.

  Returns:
    Dict mapping each available port to its location in the filesystem.
  """
  platform_dict = {}
  for path in port_root_paths:
    for port in PlatformInfo.EnumeratePorts(path):
      platform_dict[port.port_name] = port.path
  return platform_dict


def GetAllPorts():
  """Gets all available starboard ports from the host app.

  Returns:
    Dictionary mapping port names to their path in the filesystem.
  """
  port_root_paths = environment.GetStarboardPortRoots()
  return _GetAllPlatforms(port_root_paths)


class PlatformInfo(object):
  """Information about a specific starboard port."""

  @classmethod
  def EnumeratePorts(cls, root_path, exclusion_set=None):
    """Generator that iterates over starboard ports found under |path|."""
    if not exclusion_set:
      exclusion_set = set()
    for current_path, directories, filenames in os.walk(root_path):
      # Don't walk into any directories in the exclusion set.
      directories[:] = (x for x in directories
                        if os.path.join(current_path, x) not in exclusion_set)
      # Determine if the current directory is a valid port directory.
      if _IsValidPortFilenameList(current_path, filenames):
        if current_path == root_path:
          logging.warning('Found port at search path root: %s', current_path)
        port_name = _GetPortName(root_path, current_path)
        yield PlatformInfo(port_name, current_path)

  def __init__(self, name, path):
    self.port_name = name
    self.path = path

  def ImportModule(self, root_module, module_name=None):
    """Load a platform specific python module using importlib.

    Load the python module named |module_name| relative to |root_module|.
    Args:
      module: Name of a python module to load. If None, load the platform
          directory as a python module.
      root_module: An already-loaded module
    Returns:
      A module loaded with importlib.import_module
    Throws:
      ImportError if the module fails to be loaded.
    """
    # From the relative path to the |root_module|'s directory, construct a full
    # python package name and attempt to load it.
    relative_path = os.path.relpath(
        self.path, os.path.dirname(root_module.__file__))
    components = os.path.normpath(relative_path).split(os.sep)
    components = [root_module.__name__] + components
    if module_name:
      components.append(module_name)
    full_package_name = '.'.join(components)
    return importlib.import_module(full_package_name)
