# -*- coding: utf-8 -*-
"""
Various utilities and helpers
"""

import sys
from os.path import dirname
from os.path import isabs
from os.path import normpath
from os.path import relpath


class _Distribution(object):
    def __init__(self, project_name, version):
        self.project_name = project_name
        self.version = version


try:
    from importlib import metadata
    try:
        ply_version = metadata.version('ply')
    except Exception:  # pragma: no cover
        ply_dist = None
    else:
        ply_dist = _Distribution(project_name='ply', version=ply_version)
except ImportError:  # pragma: no cover
    try:
        from pkg_resources import working_set
        from pkg_resources import Requirement
        ply_dist = working_set.find(Requirement.parse('ply'))
        # note that for **extremely** ancient versions of setuptools, e.g.
        # setuptools<0.6c11, or some very non-standard environment that does
        # not include the required metadata (e.g. pyinstaller without the
        # required metadata), will require the following workaround...
        if ply_dist:
            # convert to our private version class
            ply_dist = _Distribution(
                project_name='ply',
                version=ply_dist.version,
            )
        else:
            try:
                import ply
                ply_dist = _Distribution(
                    project_name='ply',
                    version=ply.__version__,
                )
            except ImportError:
                ply_dist = None
    except ImportError:  # pragma: no cover
        ply_dist = None

py_major = sys.version_info.major
unicode = unicode if py_major < 3 else None  # noqa: F821
str = str if sys.version_info.major > 2 else unicode  # noqa: F821


def repr_compat(s):
    """
    Since Python 2 is annoying with unicode literals, and that we are
    enforcing the usage of unicode, this ensures the repr doesn't spew
    out the unicode literal prefix.
    """

    if unicode and isinstance(s, unicode):
        return repr(s)[1:]
    else:
        return repr(s)


def generate_tab_names(name, _version='unknown'):
    """
    Return the names to lextab and yacctab modules for the given module
    name.  Typical usage should be like so::

    >>> lextab, yacctab = generate_tab_names(__name__)
    """

    package_name, module_name = name.rsplit('.', 1)

    version = (ply_dist.version if ply_dist is not None else _version).replace(
        '.', '_')
    data = (package_name, module_name, py_major, version)
    lextab = '%s.lextab_%s_py%d_ply%s' % data
    yacctab = '%s.yacctab_%s_py%d_ply%s' % data
    return lextab, yacctab


def format_lex_token(token):
    return '%s at %s:%s' % (
        repr_compat(token.value), token.lineno, getattr(token, 'colno', '?'))


def normrelpath(base, target):
    """
    This function takes the base and target arguments as paths, and
    returns an equivalent relative path from base to the target, if both
    provided paths are absolute.
    """

    if not all(map(isabs, [base, target])):
        return target

    return relpath(normpath(target), dirname(normpath(base)))
