# -*- coding: utf-8 -*-
# Copyright 2020 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Package Info (CPV) parsing."""

from __future__ import print_function

import collections
import functools
import re
import string
from typing import Union

# Define data structures for holding PV and CPV objects.
_PV_FIELDS = ['pv', 'package', 'version', 'version_no_rev', 'rev']
PV = collections.namedtuple('PV', _PV_FIELDS)
# See ebuild(5) man page for the field specs these fields are based on.
# Notably, cpv does not include the revision, cpf does.
_CPV_FIELDS = ['category', 'cp', 'cpv', 'cpf'] + _PV_FIELDS
CPV = collections.namedtuple('CPV', _CPV_FIELDS)

# Package matching regexp, as dictated by package manager specification:
# https://www.gentoo.org/proj/en/qa/pms.xml
_pkg = r'(?P<package>' + r'[\w+][\w+-]*)'
_ver = (r'(?P<version>'
        r'(?P<version_no_rev>(\d+)((\.\d+)*)([a-z]?)'
        r'((_(pre|p|beta|alpha|rc)\d*)*))'
        r'(-(?P<rev>r(\d+)))?)')
_pvr_re = re.compile(r'^(?P<pv>%s-%s)$' % (_pkg, _ver), re.VERBOSE)


def _SplitPV(pv, strict=True):
  """Takes a PV value and splits it into individual components.

  Deprecated, use parse() instead.

  Args:
    pv: Package name and version.
    strict: If True, returns None if version or package name is missing.
      Otherwise, only package name is mandatory.

  Returns:
    A collection with named members:
      pv, package, version, version_no_rev, rev
  """
  m = _pvr_re.match(pv)

  if m is None and strict:
    return None

  if m is None:
    return PV(**{'pv': None, 'package': pv, 'version': None,
                 'version_no_rev': None, 'rev': None})

  return PV(**m.groupdict())


def SplitCPV(cpv, strict=True):
  """Splits a CPV value into components.

  Deprecated, use parse() instead.

  Args:
    cpv: Category, package name, and version of a package.
    strict: If True, returns None if any of the components is missing.
      Otherwise, only package name is mandatory.

  Returns:
    A collection with named members:
      category, pv, package, version, version_no_rev, rev
  """
  chunks = cpv.split('/')
  if len(chunks) > 2:
    raise ValueError('Unexpected package format %s' % cpv)
  if len(chunks) == 1:
    category = None
  else:
    category = chunks[0]

  m = _SplitPV(chunks[-1], strict=strict)
  if strict and (category is None or m is None):
    return None

  # Gather parts and build each field. See ebuild(5) man page for spec.
  cp_fields = (category, m.package)
  cp = '%s/%s' % cp_fields if all(cp_fields) else None

  cpv_fields = (cp, m.version_no_rev)
  real_cpv = '%s-%s' % cpv_fields if all(cpv_fields) else None

  cpf_fields = (real_cpv, m.rev)
  cpf = '%s-%s' % cpf_fields if all(cpf_fields) else real_cpv

  return CPV(category=category, cp=cp, cpv=real_cpv, cpf=cpf, **m._asdict())


def parse(cpv: Union[str, CPV, 'PackageInfo']):
  """Parse a package to a PackageInfo object.

  Args:
    cpv: Any package type. This function can parse strings, translate CPVs to a
      PackageInfo instance, and will simply return the argument if given a
      PackageInfo instance.

  Returns:
    PackageInfo
  """
  if isinstance(cpv, PackageInfo):
    return cpv
  elif isinstance(cpv, CPV):
    parsed = cpv
  else:
    parsed = SplitCPV(cpv, strict=False)
  # Temporary measure. SplitCPV parses X-r1 with the revision as r1.
  # Once the SplitCPV function has been fully deprecated we can switch
  # the regex to exclude the r from what it parses as the revision instead.
  # TODO: Change the regex to parse the revision without the r.
  revision = parsed.rev.replace('r', '') if parsed.rev else None
  return PackageInfo(
      category=parsed.category,
      package=parsed.package,
      version=parsed.version_no_rev,
      revision=revision)


class PackageInfo(object):
  """Read-only class to hold and format commonly used package information."""

  def __init__(self, category=None, package=None, version=None, revision=None):
    # Private attributes to enforce read-only. Particularly to allow use of
    # lru_cache for formatting.
    self._category = category
    self._package = package
    self._version = version
    self._revision = int(revision) if revision else 0

  def __eq__(self, other):
    try:
      return (self.category == other.category and
              self.package == other.package and
              str(self.version) == str(other.version) and
              str(self.revision) == str(other.revision))
    except AttributeError:
      return False

  def __hash__(self):
    return hash((self._category, self._package, self._version, self._revision))

  def __repr__(self):
    return f'PackageInfo<{str(self)}>'

  def __str__(self):
    return self.cpvr or self.atom

  @functools.lru_cache()
  def __format__(self, format_spec):
    """Formatter function.

    The format |spec| is a format string containing any combination of:
    {c}, {p}, {v}, or {r} for the package's category, package name, version,
    or revision, respectively, or any of the class' {attribute}s.
    e.g. {c}/{p} or {atom} for a package's atom (i.e. category/package_name).
    """
    fmtter = string.Formatter()
    base_dict = {
        'c': self.category,
        'p': self.package,
        'v': self.version,
        # Force 'r' to be None when we have 0 to avoid -r0 suffixes.
        'r': self.revision or None,
    }
    fields = (x for _, x, _, _ in fmtter.parse(format_spec) if x)
    # Setting base_dict.get(x) as the default value for getattr allows it to
    # fall back to valid, falsey values in the base_dict rather than
    # overwriting them with None, i.e. 0 for version or revision.
    fmt_dict = {x: getattr(self, x, base_dict.get(x)) for x in fields}

    # We can almost do `if all(fmt_dict.values()):` to just check for falsey
    # values here, but 0 is a valid version value.
    if any(v in ('', None) for v in fmt_dict.values()):
      return ''

    return format_spec.format(**fmt_dict)

  @property
  def category(self):
    return self._category

  @property
  def package(self):
    return self._package

  @property
  def version(self):
    return self._version

  @property
  def revision(self):
    return self._revision

  @property
  def cpv(self):
    return format(self, '{c}/{p}-{v}')

  @property
  def cpvr(self):
    return format(self, '{cpv}-r{r}') or self.cpv

  @property
  def cpf(self):
    """CPF is the portage name for cpvr, provided to simplify transition."""
    return self.cpvr

  @property
  def atom(self):
    return format(self, '{c}/{p}')

  @property
  def cp(self):
    return self.atom

  @property
  def pv(self):
    return format(self, '{p}-{v}')

  @property
  def pvr(self):
    return format(self, '{pv}-r{r}') or self.pv

  @property
  def vr(self):
    return format(self, '{v}-r{r}') or self.version

  @property
  def ebuild(self):
    return format(self, '{pvr}.ebuild')

  @property
  def relative_path(self):
    """Path of the ebuild relative to its overlay."""
    return format(self, '{c}/{p}/{ebuild}')

  def revision_bump(self):
    """Get a PackageInfo instance with an incremented revision."""
    return PackageInfo(self.category, self.package, self.version,
                       self.revision + 1)

  def with_version(self, version):
    """Get a PackageInfo instance with the new, specified version."""
    return PackageInfo(self.category, self.package, version)

  def to_cpv(self):
    """Get a CPV instance of this PackageInfo.

    This method is provided only to allow compatibility with functions that
    have not yet been converted to use PackageInfo objects. This function will
    be removed when the CPV namedtuple is removed.
    """
    return SplitCPV(self.cpvr)
