from functools import partial
from os import environ

from invocations import travis
from invocations.checks import blacken
from invocations.docs import docs, www, sites, watch_docs
from invocations.pytest import test, integration, coverage
from invocations.packaging import release
from invocations.util import tmpdir

from invoke import Collection, task
from invoke.util import LOG_FORMAT


# Neuter the normal release.publish task to prevent accidents, then reinstate
# it as a custom task that does dual fabric-xxx and fabric2-xxx releases.
# TODO: tweak this once release.all_ actually works right...sigh
# TODO: if possible, try phrasing as a custom build that builds x2, and then
# convince the vanilla publish() to use that custom build instead of its local
# build?
# NOTE: this skips the dual_wheels, alt_python bits the upstream task has,
# which are at the moment purely for Invoke's sake (as it must publish explicit
# py2 vs py3 wheels due to some vendored dependencies)
@task
def publish(
    c,
    sdist=True,
    wheel=False,
    index=None,
    sign=False,
    dry_run=False,
    directory=None,
    check_desc=False,
):
    # TODO: better pattern for merging kwargs + config
    config = c.config.get("packaging", {})
    index = config.get("index", index)
    sign = config.get("sign", sign)
    check_desc = config.get("check_desc", check_desc)
    # Initial sanity check, if needed. Will die usefully.
    # TODO: this could also get factored out harder in invocations. shrug. it's
    # like 3 lines total...
    if check_desc:
        c.run("python setup.py check -r -s")
    with tmpdir(skip_cleanup=dry_run, explicit=directory) as directory:
        # Doesn't reeeeally need to be a partial, but if we start having to add
        # a kwarg to one call or the other, it's nice
        builder = partial(
            release.build, c, sdist=sdist, wheel=wheel, directory=directory
        )
        # Vanilla build
        builder()
        # Fabric 2 build
        environ["PACKAGE_AS_FABRIC2"] = "yes"
        builder()
        # Upload
        release.upload(c, directory, index, sign, dry_run)


# Better than nothing, since we haven't solved "pretend I have some other
# task's signature" yet...
publish.__doc__ = release.publish.__doc__
my_release = Collection(
    "release", release.build, release.status, publish, release.prepare
)

ns = Collection(
    blacken,
    coverage,
    docs,
    integration,
    my_release,
    sites,
    test,
    travis,
    watch_docs,
    www,
)
ns.configure(
    {
        "tests": {
            # TODO: have pytest tasks honor these?
            "package": "fabric",
            "logformat": LOG_FORMAT,
        },
        "packaging": {
            # NOTE: this is currently for identifying the source directory.
            # Should it get used for actual releasing, needs changing.
            "package": "fabric",
            "sign": True,
            "wheel": True,
            "check_desc": True,
            "changelog_file": "sites/www/changelog.rst",
        },
        # TODO: perhaps move this into a tertiary, non automatically loaded,
        # conf file so that both this & the code under test can reference it?
        # Meh.
        "travis": {
            "sudo": {"user": "sudouser", "password": "mypass"},
            "black": {"version": "18.6b4"},
        },
    }
)
