# Portions Copyright (c) Facebook, Inc. and its affiliates.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2.

# Copyright (c) Mercurial Contributors.
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.

"""Utility functions related to Windows support, but which must be callable
on all platforms.
"""

from typing import Optional

from . import i18n


_ = i18n._
_winreservedchars = ':*?"<>|'
_winreservednames = {
    "con",
    "prn",
    "aux",
    "nul",
    "com1",
    "com2",
    "com3",
    "com4",
    "com5",
    "com6",
    "com7",
    "com8",
    "com9",
    "lpt1",
    "lpt2",
    "lpt3",
    "lpt4",
    "lpt5",
    "lpt6",
    "lpt7",
    "lpt8",
    "lpt9",
}


def checkwinfilename(path):
    # type: (str) -> Optional[str]
    r"""Check that the base-relative path is a valid filename on Windows.
    Returns None if the path is ok, or a UI string describing the problem.

    >>> checkwinfilename("just/a/normal/path")
    >>> checkwinfilename("foo/bar/con.xml")
    "filename contains 'con', which is reserved on Windows"
    >>> checkwinfilename("foo/con.xml/bar")
    "filename contains 'con', which is reserved on Windows"
    >>> checkwinfilename("foo/bar/xml.con")
    >>> checkwinfilename("foo/bar/AUX/bla.txt")
    "filename contains 'AUX', which is reserved on Windows"
    >>> checkwinfilename("foo/bar/bla:.txt")
    "filename contains ':', which is reserved on Windows"
    >>> checkwinfilename("foo/bar/b\07la.txt")
    "filename contains '\\x07', which is invalid on Windows"
    >>> checkwinfilename("foo/bar/bla ")
    "filename ends with ' ', which is not allowed on Windows"
    >>> checkwinfilename("../bar")
    >>> checkwinfilename("foo\\")
    "filename ends with '\\', which is invalid on Windows"
    >>> checkwinfilename("foo\\/bar")
    "directory name ends with '\\', which is invalid on Windows"
    """
    if path.endswith("\\"):
        return _("filename ends with '\\', which is invalid on Windows")
    if "\\/" in path:
        return _("directory name ends with '\\', which is invalid on Windows")
    for n in path.replace("\\", "/").split("/"):
        if not n:
            continue
        for c in n:
            if c in _winreservedchars:
                return _("filename contains '%s', which is reserved " "on Windows") % c
            if ord(c) <= 31:
                return _("filename contains %r, which is invalid " "on Windows") % c
        base = n.split(".")[0]
        if base and base.lower() in _winreservednames:
            return _("filename contains '%s', which is reserved " "on Windows") % base
        t = n[-1:]
        if t in ". " and n not in "..":
            return _("filename ends with '%s', which is not allowed " "on Windows") % t
