#!/usr/bin/python3
#
# Copyright (C) 2011, Stefano Rivera <stefanor@ubuntu.com>
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

import optparse
import sys

from ubuntutools.lp.lpapicache import (
    Launchpad,
    Distribution,
    PersonTeam,
    Packageset,
    PackageNotFoundException,
    SeriesNotFoundException,
)
from ubuntutools.misc import split_release_pocket

from ubuntutools import getLogger

Logger = getLogger()


def parse_arguments():
    """Parse arguments and return (options, package)"""
    parser = optparse.OptionParser("%prog [options] package")
    parser.add_option(
        "-r",
        "--release",
        default=None,
        metavar="RELEASE",
        help="Use RELEASE, rather than the current development release",
    )
    parser.add_option(
        "-a",
        "--list-uploaders",
        default=False,
        action="store_true",
        help="List all the people/teams with upload rights",
    )
    parser.add_option(
        "-t",
        "--list-team-members",
        default=False,
        action="store_true",
        help="List all team members of teams with upload rights (implies --list-uploaders)",
    )
    options, args = parser.parse_args()

    if len(args) != 1:
        parser.error("One (and only one) package must be specified")
    package = args[0]

    if options.list_team_members:
        options.list_uploaders = True

    return (options, package)


def main():
    """Query upload permissions"""
    options, package = parse_arguments()
    # Need to be logged in to see uploaders:
    Launchpad.login()

    ubuntu = Distribution("ubuntu")
    archive = ubuntu.getArchive()
    if options.release is None:
        options.release = ubuntu.getDevelopmentSeries().name
    try:
        release, pocket = split_release_pocket(options.release)
        series = ubuntu.getSeries(release)
    except SeriesNotFoundException as e:
        Logger.error(str(e))
        sys.exit(2)

    try:
        spph = archive.getSourcePackage(package)
    except PackageNotFoundException as e:
        Logger.error(str(e))
        sys.exit(2)
    component = spph.getComponent()
    if options.list_uploaders and (
        pocket != "Release"
        or series.status in ("Experimental", "Active Development", "Pre-release Freeze")
    ):

        component_uploader = archive.getUploadersForComponent(component_name=component)[0]
        Logger.info("All upload permissions for %s:" % package)
        Logger.info("")
        Logger.info("Component (%s)" % component)
        Logger.info("============" + ("=" * len(component)))
        print_uploaders([component_uploader], options.list_team_members)

        packagesets = sorted(
            Packageset.setsIncludingSource(distroseries=series, sourcepackagename=package),
            key=lambda p: p.name,
        )
        if packagesets:
            Logger.info("")
            Logger.info("Packagesets")
            Logger.info("===========")
            for packageset in packagesets:
                Logger.info("")
                Logger.info("%s:" % packageset.name)
                print_uploaders(
                    archive.getUploadersForPackageset(packageset=packageset),
                    options.list_team_members,
                )

        ppu_uploaders = archive.getUploadersForPackage(source_package_name=package)
        if ppu_uploaders:
            Logger.info("")
            Logger.info("Per-Package-Uploaders")
            Logger.info("=====================")
            Logger.info("")
            print_uploaders(ppu_uploaders, options.list_team_members)
        Logger.info("")

    if PersonTeam.me.canUploadPackage(archive, series, package, component, pocket):
        Logger.info("You can upload %s to %s." % (package, options.release))
    else:
        Logger.info("You can not upload %s to %s, yourself." % (package, options.release))
        if (
            series.status in ("Current Stable Release", "Supported", "Obsolete")
            and pocket == "Release"
        ):
            Logger.info(
                "%s is in the '%s' state. You may want to query the %s-proposed pocket."
                % (release, series.status, release)
            )
        else:
            Logger.info(
                "But you can still contribute to it via the sponsorship "
                "process: https://wiki.ubuntu.com/SponsorshipProcess"
            )
            if not options.list_uploaders:
                Logger.info(
                    "To see who has the necessary upload rights, "
                    "use the --list-uploaders option."
                )
        sys.exit(1)


def print_uploaders(uploaders, expand_teams=False, prefix=""):
    """Given a list of uploaders, pretty-print them all
    Each line is prefixed with prefix.
    If expand_teams is set, recurse, adding more spaces to prefix on each
    recursion.
    """
    for uploader in sorted(uploaders, key=lambda p: p.display_name):
        Logger.info(
            "%s* %s (%s)%s"
            % (prefix, uploader.display_name, uploader.name, " [team]" if uploader.is_team else "")
        )
        if expand_teams and uploader.is_team:
            print_uploaders(uploader.participants, True, prefix=prefix + "  ")


if __name__ == "__main__":
    main()