# Copyright 2017 The Abseil Authors.
#
# 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.

"""Contains Flag class - information about single command-line flag.

Do NOT import this module directly. Import the flags package and use the
aliases defined at the package level instead.
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import functools

from absl.flags import _argument_parser
from absl.flags import _exceptions
from absl.flags import _helpers


@functools.total_ordering
class Flag(object):
  """Information about a command-line flag.

  'Flag' objects define the following fields:
    .name - the name for this flag;
    .default - the default value for this flag;
    .default_unparsed - the unparsed default value for this flag.
    .default_as_str - default value as repr'd string, e.g., "'true'" (or None);
    .value - the most recent parsed value of this flag; set by parse();
    .help - a help string or None if no help is available;
    .short_name - the single letter alias for this flag (or None);
    .boolean - if 'true', this flag does not accept arguments;
    .present - true if this flag was parsed from command line flags;
    .parser - an ArgumentParser object;
    .serializer - an ArgumentSerializer object;
    .allow_override - the flag may be redefined without raising an error, and
                      newly defined flag overrides the old one.
    .allow_override_cpp - the flag may be redefined in C++ without raising an
                          error, value "transferred" to C++, and the flag is
                          replaced by the C++ flag after init;
    .allow_hide_cpp - the flag may be redefined despite hiding a C++ flag with
                      the same name;
    .using_default_value - the flag value has not been set by user;
    .allow_overwrite - the flag may be parsed more than once without raising
                       an error, the last set value will be used;
    .allow_using_method_names - whether this flag can be defined even if it has
                                a name that conflicts with a FlagValues method.

  The only public method of a 'Flag' object is parse(), but it is
  typically only called by a 'FlagValues' object.  The parse() method is
  a thin wrapper around the 'ArgumentParser' parse() method.  The parsed
  value is saved in .value, and the .present attribute is updated.  If
  this flag was already present, an Error is raised.

  parse() is also called during __init__ to parse the default value and
  initialize the .value attribute.  This enables other python modules to
  safely use flags even if the __main__ module neglects to parse the
  command line arguments.  The .present attribute is cleared after
  __init__ parsing.  If the default value is set to None, then the
  __init__ parsing step is skipped and the .value attribute is
  initialized to None.

  Note: The default value is also presented to the user in the help
  string, so it is important that it be a legal value for this flag.
  """

  def __init__(self, parser, serializer, name, default, help_string,
               short_name=None, boolean=False, allow_override=False,
               allow_override_cpp=False, allow_hide_cpp=False,
               allow_overwrite=True, allow_using_method_names=False):
    self.name = name

    if not help_string:
      help_string = '(no help available)'

    self.help = help_string
    self.short_name = short_name
    self.boolean = boolean
    self.present = 0
    self.parser = parser
    self.serializer = serializer
    self.allow_override = allow_override
    self.allow_override_cpp = allow_override_cpp
    self.allow_hide_cpp = allow_hide_cpp
    self.allow_overwrite = allow_overwrite
    self.allow_using_method_names = allow_using_method_names

    self.using_default_value = True
    self._value = None
    self.validators = []
    if allow_hide_cpp and allow_override_cpp:
      raise _exceptions.Error(
          "Can't have both allow_hide_cpp (means use Python flag) and "
          'allow_override_cpp (means use C++ flag after InitGoogle)')

    self._set_default(default)

  @property
  def value(self):
    return self._value

  @value.setter
  def value(self, value):
    self._value = value

  def __hash__(self):
    return hash(id(self))

  def __eq__(self, other):
    return self is other

  def __lt__(self, other):
    if isinstance(other, Flag):
      return id(self) < id(other)
    return NotImplemented

  def _get_parsed_value_as_string(self, value):
    """Returns parsed flag value as string."""
    if value is None:
      return None
    if self.serializer:
      return repr(self.serializer.serialize(value))
    if self.boolean:
      if value:
        return repr('true')
      else:
        return repr('false')
    return repr(_helpers.str_or_unicode(value))

  def parse(self, argument):
    """Parses string and sets flag value.

    Args:
      argument: str or the correct flag value type, argument to be parsed.
    """
    if self.present and not self.allow_overwrite:
      raise _exceptions.IllegalFlagValueError(
          'flag --%s=%s: already defined as %s' % (
              self.name, argument, self.value))
    self.value = self._parse(argument)
    self.present += 1

  def _parse(self, argument):
    """Internal parse function.

    It returns the parsed value, and does not modify class states.

    Args:
      argument: str or the correct flag value type, argument to be parsed.

    Returns:
      The parsed value.
    """
    try:
      return self.parser.parse(argument)
    except (TypeError, ValueError) as e:  # Recast as IllegalFlagValueError.
      raise _exceptions.IllegalFlagValueError(
          'flag --%s=%s: %s' % (self.name, argument, e))

  def unparse(self):
    self.value = self.default
    self.using_default_value = True
    self.present = 0

  def serialize(self):
    if self.value is None:
      return ''
    if self.boolean:
      if self.value:
        return '--%s' % self.name
      else:
        return '--no%s' % self.name
    else:
      if not self.serializer:
        raise _exceptions.Error(
            'Serializer not present for flag %s' % self.name)
      return '--%s=%s' % (self.name, self.serializer.serialize(self.value))

  def _set_default(self, value):
    """Changes the default value (and current value too) for this Flag."""
    self.default_unparsed = value
    if value is None:
      self.default = None
    else:
      self.default = self._parse(value)
    self.default_as_str = self._get_parsed_value_as_string(self.default)
    if self.using_default_value:
      self.value = self.default

  def flag_type(self):
    """Returns a str that describes the type of the flag.

    NOTE: we use strings, and not the types.*Type constants because
    our flags can have more exotic types, e.g., 'comma separated list
    of strings', 'whitespace separated list of strings', etc.
    """
    return self.parser.flag_type()

  def _create_xml_dom_element(self, doc, module_name, is_key=False):
    """Returns an XML element that contains this flag's information.

    This is information that is relevant to all flags (e.g., name,
    meaning, etc.).  If you defined a flag that has some other pieces of
    info, then please override _ExtraXMLInfo.

    Please do NOT override this method.

    Args:
      doc: minidom.Document, the DOM document it should create nodes from.
      module_name: str,, the name of the module that defines this flag.
      is_key: boolean, True iff this flag is key for main module.

    Returns:
      A minidom.Element instance.
    """
    element = doc.createElement('flag')
    if is_key:
      element.appendChild(_helpers.create_xml_dom_element(doc, 'key', 'yes'))
    element.appendChild(_helpers.create_xml_dom_element(
        doc, 'file', module_name))
    # Adds flag features that are relevant for all flags.
    element.appendChild(_helpers.create_xml_dom_element(doc, 'name', self.name))
    if self.short_name:
      element.appendChild(_helpers.create_xml_dom_element(
          doc, 'short_name', self.short_name))
    if self.help:
      element.appendChild(_helpers.create_xml_dom_element(
          doc, 'meaning', self.help))
    # The default flag value can either be represented as a string like on the
    # command line, or as a Python object.  We serialize this value in the
    # latter case in order to remain consistent.
    if self.serializer and not isinstance(self.default, str):
      if self.default is not None:
        default_serialized = self.serializer.serialize(self.default)
      else:
        default_serialized = ''
    else:
      default_serialized = self.default
    element.appendChild(_helpers.create_xml_dom_element(
        doc, 'default', default_serialized))
    element.appendChild(_helpers.create_xml_dom_element(
        doc, 'current', self.value))
    element.appendChild(_helpers.create_xml_dom_element(
        doc, 'type', self.flag_type()))
    # Adds extra flag features this flag may have.
    for e in self._extra_xml_dom_elements(doc):
      element.appendChild(e)
    return element

  def _extra_xml_dom_elements(self, doc):
    """Returns extra info about this flag in XML.

    "Extra" means "not already included by _create_xml_dom_element above."

    Args:
      doc: minidom.Document, the DOM document it should create nodes from.

    Returns:
      A list of minidom.Element.
    """
    # Usually, the parser knows the extra details about the flag, so
    # we just forward the call to it.
    return self.parser._custom_xml_dom_elements(doc)  # pylint: disable=protected-access


class BooleanFlag(Flag):
  """Basic boolean flag.

  Boolean flags do not take any arguments, and their value is either
  True (1) or False (0).  The false value is specified on the command
  line by prepending the word 'no' to either the long or the short flag
  name.

  For example, if a Boolean flag was created whose long name was
  'update' and whose short name was 'x', then this flag could be
  explicitly unset through either --noupdate or --nox.
  """

  def __init__(self, name, default, help, short_name=None, **args):  # pylint: disable=redefined-builtin
    p = _argument_parser.BooleanParser()
    super(BooleanFlag, self).__init__(
        p, None, name, default, help, short_name, 1, **args)


class EnumFlag(Flag):
  """Basic enum flag; its value can be any string from list of enum_values."""

  def __init__(self, name, default, help, enum_values,  # pylint: disable=redefined-builtin
               short_name=None, case_sensitive=True, **args):
    p = _argument_parser.EnumParser(enum_values, case_sensitive)
    g = _argument_parser.ArgumentSerializer()
    super(EnumFlag, self).__init__(
        p, g, name, default, help, short_name, **args)
    self.help = '<%s>: %s' % ('|'.join(enum_values), self.help)

  def _extra_xml_dom_elements(self, doc):
    elements = []
    for enum_value in self.parser.enum_values:
      elements.append(_helpers.create_xml_dom_element(
          doc, 'enum_value', enum_value))
    return elements


class MultiFlag(Flag):
  """A flag that can appear multiple time on the command-line.

  The value of such a flag is a list that contains the individual values
  from all the appearances of that flag on the command-line.

  See the __doc__ for Flag for most behavior of this class.  Only
  differences in behavior are described here:

    * The default value may be either a single value or a list of values.
      A single value is interpreted as the [value] singleton list.

    * The value of the flag is always a list, even if the option was
      only supplied once, and even if the default value is a single
      value
  """

  def __init__(self, *args, **kwargs):
    super(MultiFlag, self).__init__(*args, **kwargs)
    self.help += ';\n    repeat this option to specify a list of values'

  def parse(self, arguments):
    """Parses one or more arguments with the installed parser.

    Args:
      arguments: a single argument or a list of arguments (typically a
        list of default values); a single argument is converted
        internally into a list containing one item.
    """
    new_values = self._parse(arguments)
    if self.present:
      self.value.extend(new_values)
    else:
      self.value = new_values
    self.present += len(new_values)

  def _parse(self, arguments):
    if not isinstance(arguments, list):
      # Default value may be a list of values.  Most other arguments
      # will not be, so convert them into a single-item list to make
      # processing simpler below.
      arguments = [arguments]

    return [super(MultiFlag, self)._parse(item) for item in arguments]

  def serialize(self):
    """See base class."""
    if not self.serializer:
      raise _exceptions.Error(
          'Serializer not present for flag %s' % self.name)
    if self.value is None:
      return ''

    s = ''

    multi_value = self.value

    for self.value in multi_value:
      if s: s += ' '
      s += Flag.serialize(self)

    self.value = multi_value

    return s

  def flag_type(self):
    """See base class."""
    return 'multi ' + self.parser.flag_type()

  def _extra_xml_dom_elements(self, doc):
    elements = []
    if hasattr(self.parser, 'enum_values'):
      for enum_value in self.parser.enum_values:
        elements.append(_helpers.create_xml_dom_element(
            doc, 'enum_value', enum_value))
    return elements
