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

"""Extracts the API versions for all available builds.

  Example usage:
    cd cobalt/src/
    extract_starboard_versions.py
"""

from __future__ import print_function

import fnmatch
import os
import re
import sys
import platform
import paths

# Sometimes files have weird encodings. This function will use a variety of
# hand selected encoders that work on the starboard codebase.
def AutoDecodeString(file_data):
  for encoding in {'UTF-8', 'utf_16', 'windows-1253', 'iso-8859-7', 'macgreek'}:
    try:
      return file_data.decode(encoding)
    except:
      continue
  raise IOError('Could not read file')

# Given a search_term, this will open the file_path and return the first
# line that contains the search term. This will ignore C-style comments.
def SearchInFileReturnFirstMatchingLine(file_path, search_term):
  try:
    lines = OpenFileAndDecodeLinesAndRemoveComments(file_path)
    for line in lines:
      if search_term in line:
        return line
    return None
  except IOError:
    print ('  error while reading file ', file_path)

# Opens a header or cc file and decodes it to utf8 using a variety
# of decoders. All lines will have their comments stripped out.
# This will return the lines of the given file.
def OpenFileAndDecodeLinesAndRemoveComments(file_path):
  with open(file_path, 'rb+') as fd:
    lines = AutoDecodeString(fd.read()).splitlines()
    # remove c-style comments.
    lines = [ re.sub('//.*', '', line) for line in lines]
    return lines


# Given a file_path, return all include files that it contains.
def FindIncludeFiles(file_path):
  try:
    output_list = []
    lines = OpenFileAndDecodeLinesAndRemoveComments(file_path)
    for line in lines:
      # Remove c-style comments.
      if '#include' in line:
        line = re.sub('#include ', '', line).replace('"', '')
        output_list.append(line)
    return output_list
  except IOError:
    print ('  error while reading file ', file_path)

# Searches from the search_location for a configuration.h file that
# contains the definition of the SB_EXPERIMENTAL_API_VERSION and then
# returns that as type int.
def ExtractExperimentalApiVersion(config_file_path):
  needle = '#define SB_EXPERIMENTAL_API_VERSION'
  line = SearchInFileReturnFirstMatchingLine(
      config_file_path,
      '#define SB_EXPERIMENTAL_API_VERSION')
  if not line:
    raise ValueError('Could not find ' + needle + ' in ' + config_file_path)

  elements = line.split(' ')
  exp_api_version = int(elements[2])
  return exp_api_version

# Given platform path, this function will try and find the version. Returns
# either the version if found, or None.
# If the version string is returned, note that it could be
# 'SB_EXPERIMENTAL_VERSION' or a number string.
def FindVersion(platform_path):
  api_version_str = '#define SB_API_VERSION'
  result = SearchInFileReturnFirstMatchingLine(platform_path, api_version_str)
  if not result:
    return None
  version_str = result.replace(api_version_str, '')
  return version_str.strip()

# Given the path to the platform_include_file, this will find the include
# files with "configuration_public.h" in the name and return those.
def FindConfigIncludefile(platform_path_config_file):
  include_files = FindIncludeFiles(platform_path_config_file)
  include_files = filter(lambda x: 'configuration_public.h' in x, include_files)
  return include_files

# Given the input starboard directory, this will return a map of
# 'platform_name' -> 'full_path_to_platform'
def GeneratePlatformPathMap(starboard_dir):
  ports = [p for p in platform.PlatformInfo.EnumeratePorts(starboard_dir)]
  def GenPath(p):
    full_path = os.path.abspath(os.path.join(p.path, 'configuration_public.h'))
    if not os.path.exists(full_path):
      raise IOError("Could not find path " + full_path)
    return full_path

  port_dict = {}
  for p in ports:
    port_dict[p.port_name] = GenPath(p)
  return port_dict

# Given the root starboard directory, and the full path to the platform,
# this function will search for the API_VERSION of the platform. It will
# first see if the version is defined within the include file, if it is
# not then the include paths for shared platform configurations are
# searched in the recursive step.
def FindVersionRecursive(starboard_dir, platform_path):
  version_str = FindVersion(platform_path)
  if version_str:
    return version_str
  else:
    config_include_paths = FindConfigIncludefile(platform_path)
    if len(config_include_paths) == 0:
      return "<UNKNOWN>"
    elif len(config_include_paths) > 1:
      return "<AMBIGUIOUS>"
    else:
      include_path = config_include_paths[0]
      include_path = re.sub(r'^starboard/', '', include_path)
      full_include_path = os.path.join(starboard_dir, include_path)
      return FindVersionRecursive(starboard_dir, full_include_path)

def Main():
  print('\n***** Listing the api versions of all first party ports. *****\n')

  port_dict = GeneratePlatformPathMap(paths.STARBOARD_ROOT)

  experimental_api_version = ExtractExperimentalApiVersion(
      os.path.join(paths.STARBOARD_ROOT, 'configuration.h'))

  path_map = {}

  print('Experimental API Version: ' + str(experimental_api_version) + '\n')

  for platform_name, platform_path in port_dict.iteritems():
    version_str = FindVersionRecursive(paths.STARBOARD_ROOT, platform_path)
    if 'SB_EXPERIMENTAL_API_VERSION' in version_str:
      version_str = str(experimental_api_version)
    path_map[platform_name] = version_str

  for platform_name, api_version in sorted(path_map.iteritems()):
    print(platform_name + ': ' + api_version)

  sys.exit(0)

if __name__ == '__main__':
  # All functionality stored in Main() to avoid py-lint from warning about
  # about shadowing global variables in local functions.
  Main()
