#!/usr/bin/python

from optparse import OptionParser
import logging
import sys

from launchpadlib.launchpad import Launchpad


SCRIPT_NAME = 'share-projects-with-team'

logging.basicConfig(format='%(levelname)s: %(message)s')
log = logging.getLogger(SCRIPT_NAME)
log.setLevel(logging.INFO)

sharing_policies = {
    'Public': set(['Private', 'Private Security']),
    'Public, can be proprietary': set([
        'Private', 'Private Security', 'Proprietary']),
    'Proprietary, can be public': set([
        'Private', 'Private Security', 'Proprietary']),
    'Proprietary': set(['Proprietary']),
    }


class LpProjectSharer(object):
    """Migrate a ~launchpad project to use sharing."""

    def __init__(self, lp, service, project, team, team_members):
        self.lp = lp
        self.service = service
        self.project = project
        self.team = team
        self.team_members = team_members

    def share(self):
        if self.missing_sharing_polcies():
            sys.exit(2)
        self.share_with_team()
        self.unshare_with_team_members()

    def missing_sharing_polcies(self):
        missing_policies = False
        if self.project.bug_sharing_policy is None:
            log.info(
                'Bugs Sharing Policy for %s is not set.' % self.project.name)
            missing_policies = True
        if self.project.branch_sharing_policy is None:
            log.info(
                'Branch Sharing Policy for %s is not set.' % self.project.name)
            missing_policies = True
        return missing_policies

    def share_with_team(self):
        bug_policies = sharing_policies[self.project.bug_sharing_policy]
        branch_policies = sharing_policies[self.project.branch_sharing_policy]
        all_policies = bug_policies | branch_policies
        log.info(
            'Sharing %s with %s in %s.', ', '.join(all_policies),
            self.team.name, self.project.name)
        permissions = {}
        for permission in all_policies:
            permissions[permission] = 'All'
        self.service.sharePillarInformation(
            pillar=self.project, grantee=self.team, permissions=permissions)

    def unshare_with_team_members(self):
        grantees = self.service.getPillarGranteeData(pillar=self.project)
        grants = [g for g in grantees if g['name'] in self.team_members]
        for grant in grants:
            log.info(
                'Revoking direct grant for team member %s.', grant['name'])
            member = self.team_members[grant['name']]
            self.service.deletePillarGrantee(
                pillar=self.project, grantee=member)


def get_option_parser():
    """Return the option parser for this program."""
    usage = "usage: %%prog [options] \n"
    parser = OptionParser(usage=usage)
    parser.add_option(
        "-e", "--environment", dest="env",
        help="The environment to use")
    parser.set_defaults(
        env='https://api.launchpad.net',
        )
    return parser


def main(argv):
    parser = get_option_parser()
    (options, args_) = parser.parse_args(args=argv)
    team_name = args_.pop(0)
    project_names = args_
    lp = Launchpad.login_with(
        SCRIPT_NAME, service_root=options.env, version='devel')
    # The service must be loaded using the full URL.
    service = lp.load('%s/devel/+services/sharing' % options.env)
    team = lp.people[team_name]
    if not team.is_team:
        sys.exit(1)
    team_members = dict((m.name, m) for m in team.members if not m.is_team)
    for project_name in project_names:
        project = lp.projects[project_name]
        migrator = LpProjectSharer(lp, service, project, team, team_members)
        migrator.share()


if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
