"""
Convenience helpers for :mod:`http.cookiejar`
"""

from typing import Union, Iterable, Optional
from http.cookiejar import Cookie, CookieJar

from hyperlink import EncodedURL


def scoped_cookie(origin: Union[str, EncodedURL], name: str, value: str) -> Cookie:
    """
    Create a cookie scoped to a given URL's origin.

    You can insert the result directly into a `CookieJar`, like::

        jar = CookieJar()
        jar.set_cookie(scoped_cookie("https://example.tld", "flavor", "chocolate"))

        await treq.get("https://domain.example", cookies=jar)

    :param origin:
        A URL that specifies the domain and port number of the cookie.

        If the protocol is HTTP*S* the cookie is marked ``Secure``, meaning
        it will not be attached to HTTP requests. Otherwise the cookie will be
        attached to both HTTP and HTTPS requests

    :param name: Name of the cookie.

    :param value: Value of the cookie.

    .. note::

        This does not scope the cookies to any particular path, only the
        host, port, and scheme of the given URL.
    """
    if isinstance(origin, EncodedURL):
        url_object = origin
    else:
        url_object = EncodedURL.from_text(origin)

    secure = url_object.scheme == "https"
    port_specified = not (
        (url_object.scheme == "https" and url_object.port == 443)
        or (url_object.scheme == "http" and url_object.port == 80)
    )
    port = str(url_object.port) if port_specified else None
    domain = url_object.host
    netscape_domain = domain if "." in domain else domain + ".local"
    return Cookie(
        # Scoping
        domain=netscape_domain,
        port=port,
        secure=secure,
        port_specified=port_specified,
        # Contents
        name=name,
        value=value,
        # Constant/always-the-same stuff
        version=0,
        path="/",
        expires=None,
        discard=False,
        comment=None,
        comment_url=None,
        rfc2109=False,
        path_specified=False,
        domain_specified=False,
        domain_initial_dot=False,
        rest={},
    )


def search(
    jar: CookieJar, *, domain: str, name: Optional[str] = None
) -> Iterable[Cookie]:
    """
    Raid the cookie jar for matching cookies.

    This is O(n) on the number of cookies in the jar.

    :param jar: The `CookieJar` (or subclass thereof) to search.

    :param domain:
        Domain, as in the URL, to match. ``.local`` is appended to
        a bare hostname. Subdomains are not matched (i.e., searching
        for ``foo.bar.tld`` won't return a cookie set for ``bar.tld``).

    :param name: Cookie name to match (exactly)
    """
    netscape_domain = domain if "." in domain else domain + ".local"

    for c in jar:
        if c.domain != netscape_domain:
            continue
        if name is not None and c.name != name:
            continue
        yield c
