# Copyright 2020 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.
"""Gyp extensions, called with pymod_do_main."""
import argparse
import glob
import logging
import os
import stat
import sys


# lifted from standard lib webbrowser.py
def isexecutable(cmd):
  """Returns whether the input file is an exectuable."""
  if sys.platform[:3] == 'win':
    extensions = ('.exe', '.bat', '.cmd')
    cmd = cmd.lower()
    if cmd.endswith(extensions) and os.path.isfile(cmd):
      return cmd
    for ext in extensions:
      if os.path.isfile(cmd + ext):
        return cmd + ext
  else:
    if os.path.isfile(cmd):
      mode = os.stat(cmd)[stat.ST_MODE]
      if mode & (stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH):
        return cmd


class ExtensionCommandParser(argparse.ArgumentParser):
  """Helper class for parsing arguments to extended gyp functions."""

  def __init__(self, list_args):
    argparse.ArgumentParser.__init__(self)
    for arg in list_args:
      self.add_argument(arg)

  def error(self, message):
    print('Parse error in gyp_functions.py:' + message)
    raise NotImplementedError('Parse error:' + message)


class Extensions(object):
  """Container class for extended functionality for gyp.

  Supports operations such as:
    - file globbing
    - checking file or directory existence
    - string manipulations
    - retrieving environment variables
    - searching PATH and PYTHONPATH for programs.
  """

  def __init__(self, argv):
    parser = argparse.ArgumentParser()
    all_cmds = [x for x in dir(self) if not x.startswith('_')]
    parser.add_argument('command', help='Command to run', choices=all_cmds)
    args = parser.parse_args(argv[0:1])
    self.argv = argv[1:]
    self.command = args.command

  def call(self):
    return getattr(self, self.command)()

  def file_glob(self):
    """Glob files in dir, with pattern glob."""
    args = ExtensionCommandParser(['dir', 'pattern']).parse_args(self.argv)
    path = os.path.normpath(os.path.join(args.dir, args.pattern))
    ret = ''
    for f in glob.iglob(path):
      ret += f.replace(os.sep, '/') + ' '
    return ret.strip()

  def file_glob_sub(self):
    """Glob files, but return filenames with string replace from->to applied."""
    args = ExtensionCommandParser(
        ['dir', 'pattern', 'from_string', 'to_string']).parse_args(self.argv)
    path = os.path.normpath(os.path.join(args.dir, args.pattern))
    ret = ''
    for f in glob.iglob(path):
      ret += f.replace(os.sep, '/').replace(args.from_string,
                                            args.to_string) + ' '
    return ret.strip()

  def file_exists(self):
    """Checks if a file exists, returning a string '1' if so, or '0'."""
    args = ExtensionCommandParser(['file']).parse_args(self.argv)
    filepath = args.file.replace(os.sep, '/')
    ret = os.path.isfile(filepath)
    return str(int(ret))

  def dir_exists(self):
    """Checks if a directory exists, returning a string 'True' or 'False'."""
    args = ExtensionCommandParser(['dir']).parse_args(self.argv)
    return str(os.path.isdir(args.dir))

  def str_upper(self):
    """Converts an input string to upper case."""
    if self.argv:
      args = ExtensionCommandParser(['str']).parse_args(self.argv)
      return args.str.upper()
    return ''

  def find_program(self):
    """Searches for the input program name (.exe, .cmd or .bat)."""
    args = ExtensionCommandParser(['program']).parse_args(self.argv)
    paths_to_check = []
    # Collect all paths in PYTHONPATH.
    for i in sys.path:
      paths_to_check.append(i.replace(os.sep, '/'))
    # Then collect all paths in PATH.
    for i in os.environ['PATH'].split(os.pathsep):
      paths_to_check.append(i.replace(os.sep, '/'))
    # Check all the collected paths for the program.
    for path in paths_to_check:
      exe = os.path.join(path, args.program)
      prog = isexecutable(exe)
      if prog:
        return prog.replace(os.sep, '/')
    # If not in PYTHONPATH and PATH, check upwards until root.
    # Note: This is a rare case.
    root_dir = os.path.dirname(os.path.abspath(__file__))
    previous_dir = os.path.abspath(__file__)
    while root_dir and root_dir != previous_dir:
      exe = os.path.join(root_dir, args.program)
      prog = isexecutable(exe)
      if prog:
        return prog.replace(os.sep, '/')
      previous_dir = root_dir
      root_dir = os.path.dirname(root_dir)
    logging.error('Failed to find program.')
    return None

  def getenv(self):
    """Gets the stored value of an environment variable."""
    args = ExtensionCommandParser(['var']).parse_args(self.argv)
    value = os.getenv(args.var)
    if value is not None:
      return value.strip()
    return ''


def DoMain(argv):  # pylint: disable=invalid-name
  """Script main function."""
  return Extensions(argv).call()


if __name__ == '__main__':
  print(DoMain(sys.argv[1:]))
  sys.exit(0)
