#!/usr/bin/env python
# Copyright 2014 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.
"""Wrapper to generate build files from .gyp files."""

import argparse
import logging
import os
import sys
import textwrap

import config
import gyp_utils


SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))

# Represents all valid build configurations.
VALID_BUILD_CONFIGS = config.VALID_BUILD_CONFIGS

# Represents all supported platforms.
VALID_PLATFORMS = config.VALID_PLATFORMS

# Return values used by main().
RETVAL_SUCCESS = 0
RETVAL_ERROR = 1

def _ListAsString(items):
  return ', '.join('"%s"' % x for x in items)


def _GetHostOS():
  """Returns the name of the hosting OS."""
  host_os_names = {
      'linux2': 'linux',
      'win32': 'win',
  }

  if not sys.platform in host_os_names:
    if sys.platform == 'cygwin':
       logging.error('There may be several incompatibilities when trying to\n'
                     'build from within cygwin. When using a bash shell is\n'
                     'preferred, consider using msysgit instead (see\n'
                     'https://msysgit.github.io).\n')
    raise RuntimeError('Unsupported platform: %s' % sys.platform)

  return host_os_names[sys.platform]


def _ParseCommandLineArguments(argv):
  """Parses command line arguments."""

  parser = argparse.ArgumentParser(
      formatter_class=argparse.RawDescriptionHelpFormatter,
      description=textwrap.dedent(__doc__))

  parser.add_argument('-C', '--config', dest='build_configs', metavar='CONFIG',
                      action='append', default=[],
                      choices=VALID_BUILD_CONFIGS,
                      help='Specifies build configurations. Supported '
                      'configurations are %s. Can be specified multiple '
                      'times, creates all configurations if nothing is '
                      'given.' % _ListAsString(VALID_BUILD_CONFIGS))

  gyp_debug_options = gyp_utils.GypDebugOptions()
  parser.add_argument('-D', '--debug', dest='debug', metavar='DEBUGMODE',
                      action='append', default=[],
                      choices=gyp_debug_options + ['all'],
                      help='Turn on a debugging mode for debugging GYP. '
                      'Supported modes are %s or "all" for all of '
                      'them.' % _ListAsString(gyp_debug_options))

  parser.add_argument('--check', action='store_true',
                      help='Check format of gyp files.')
  parser.add_argument('-v', '--verbose', dest='verbose_count',
                      default=0, action='count',
                      help='Verbose level (multiple times for more).')
  parser.add_argument('platform', choices=VALID_PLATFORMS,
                      metavar='platform',
                      help='Target platform. Supported platforms are: %s.' % (
                          _ListAsString(VALID_PLATFORMS)))
  parser.add_argument('build_file', nargs='?',
                      default=os.path.join(SCRIPT_DIR, 'all.gyp'),
                      help='GYP build file. Uses all.gyp if nothing is given.')

  options = parser.parse_args(argv)

  if options.build_configs:
    # Get rid of duplicates.
    options.build_configs = list(set(options.build_configs))
  else:
    options.build_configs = VALID_BUILD_CONFIGS

  return options


def _AppendIncludes(includes, args):
  for include in includes:
    args.append('-I{}'.format(include))


def _AppendVariables(variables, args):
  for var in variables:
    args.append('-D{}={}'.format(var, variables[var]))


def _AppendGeneratorVariables(variables, args):
  for var in variables:
    args.append('-G{}={}'.format(var, variables[var]))


def _SetupLogging(options):
  logging_level = logging.WARNING
  if options.verbose_count == 1:
    logging_level = logging.INFO
  elif options.verbose_count >= 2:
    logging_level = logging.DEBUG

  logging_format = '%(message)s'
  logging.basicConfig(level=logging_level,
                      format=logging_format)


class _GypRunner(object):
  """Responsible for running GYP."""

  def __init__(self, options):
    self.options = options
    self.common_args = []
    self.platform_config = config.LoadPlatformConfig(options.platform)
    if not self.platform_config:
      raise RuntimeError('Unable to load platform configuration.')

    os.environ.update(self.platform_config.GetEnvironmentVariables())
    self._MakeCommonArguments()

  def BuildConfig(self, config_name):
    """Builds the GYP file for a given config."""

    # Make a copy of the common arguments.
    args = self.common_args[:]

    # Add config specific variables.
    variables = {
        'cobalt_config': config_name,
    }
    variables.update(self.platform_config.GetVariables(config_name))
    _AppendVariables(variables, args)

    # Add config specific generator variables.
    generator_config = '{}_{}'.format(self.options.platform, config_name)

    generator_variables = {
        'config': generator_config,
    }
    generator_variables.update(
        self.platform_config.GetGeneratorVariables(config_name))
    _AppendGeneratorVariables(generator_variables, args)

    # That target build file goes last.
    args.append(self.options.build_file)

    gyp = gyp_utils.GetGyp()
    return gyp.main(args)

  def _MakeCommonArguments(self):
    """Makes a list of GYP arguments that is common to all configurations."""

    # Flavor will be used by the generator to figure out the target platform.
    flavor = self.platform_config.GetBuildFlavor()
    source_tree_dir = gyp_utils.GetSourceTreeDir()
    self.common_args = [
        # Set the build format
        '--format={}-{}'.format(self.platform_config.GetBuildFormat(), flavor),
        # Set the depth argument to the top level directory. This will define
        # the DEPTH variable which is the relative path between the directory
        # containing the processed build file and the top level directory.
        '--depth={}'.format(source_tree_dir),
        # Set the top of the source tree.
        '--toplevel-dir={}'.format(source_tree_dir),
    ]

    # Add the source tree root to the Python path so that build files can
    # easily reference other build files in the source tree.
    sys.path.append(source_tree_dir)

    # Pass through the debug options.
    for debug in self.options.debug:
      self.common_args.append('--debug=%s' % debug)

    if self.options.check:
      self.common_args.append('--check')

    # Append GYP variables
    variables = {
        'OS': 'lb_shell',
        'cobalt_fastbuild': os.environ.get('LB_FASTBUILD', 0),
        'cobalt_version': gyp_utils.GetBuildNumber(),
        'host_os': _GetHostOS(),
        'CC': os.environ.get('CC', ''),
    }
    if self.platform_config.IsStarboard():
      variables['OS'] = 'starboard'
      platform = self.platform_config.platform
      platforms = gyp_utils.GetThirdPartyPlatforms()
      if platform in platforms:
        full_starboard_path = platforms[platform]
        assert full_starboard_path[:len(source_tree_dir)] == source_tree_dir
        starboard_path = full_starboard_path[len(source_tree_dir) + 1:]
        starboard_path.replace(os.sep, '/')
        assert starboard_path[0] not in [ os.sep, os.altsep ]
        variables['starboard_path'] = starboard_path
    _AppendVariables(variables, self.common_args)

    # Append generator variables.
    generator_variables = {
        # set output folder name, affects all generators but MSVS
        'output_dir': 'out',
    }
    _AppendGeneratorVariables(generator_variables, self.common_args)

    # Append GYPI includes which will be includes by GYP before any processed
    # build file.
    gyp_includes = [
        os.path.join(SCRIPT_DIR, 'config', 'base.gypi'),
        # TODO: Consider removing dependency on common.gypi
        # going forward by moving the required bits into config/base.gypi.
        os.path.join(source_tree_dir, 'build', 'common.gypi'),
    ]
    gyp_includes.extend(self.platform_config.GetIncludes())
    _AppendIncludes(gyp_includes, self.common_args)


def main(argv):
  if os.environ.get('GYP_DEFINES'):
    logging.error('GYP_DEFINES environment variable is not supported.')
    return RETVAL_ERROR

  options = _ParseCommandLineArguments(argv)
  _SetupLogging(options)

  try:
    gyp_runner = _GypRunner(options)
  except RuntimeError as e:
    logging.error(e)
    return RETVAL_ERROR

  for config_name in options.build_configs:
    logging.info('Building config: %s.', config_name)
    gyp_return = gyp_runner.BuildConfig(config_name)
    if gyp_return:
      logging.error('Gyp failed with error code %d.', gyp_return)
      return gyp_return

  logging.info('Done.')
  return RETVAL_SUCCESS


if __name__ == '__main__':
  sys.exit(main(sys.argv[1:]))
