#!/usr/bin/env python
# vim: ai ts=4 sts=4 et sw=4
#
# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2014 Intel, Inc
#
#    This program is free software; you can redistribute it and/or
#    modify it under the terms of the GNU General Public License
#    as published by the Free Software Foundation; version 2
#    of the License.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
#
"""
This job is triggered manually or by repa to accept or reject submissions.
"""

import os
import sys

from common.buildservice import BuildService
from common.prerelease import get_prerelease_project_name

class LocalError(Exception):
    """Local error exception."""
    pass

def get_project_by_name(build, submission, target):
    """Lookup for a project in OBS by submission or group name."""
    if submission.startswith('submitgroup/'):
        submission += '-group'
    project = get_prerelease_project_name(target, submission)
    if not build.exists(project):
        raise LocalError("Project %s doesn't exits" % project)
    meta = build.get_info(project)
    return project, meta


def resolve_submissions(build, submission, target):
    """Get list of submissions with meta. Resolves submitgroups."""
    project, meta = get_project_by_name(build, submission, target)
    if submission.startswith('submitgroup'):
        for subm in meta['submissions']:
            sprj, smeta = get_project_by_name(build, subm, target)
            yield subm, sprj, smeta
    else:
        yield submission, project, meta


def accept_or_reject(build, submission, state, target, comment=''):
    """Create SRs and set their state for one submission or for a group."""
    for name, project, meta in resolve_submissions(build, submission, target):
        print "submission %s" % str(name)

        commit = meta.get('git_commit') or meta['git_tag']
        submitter = meta.get('submitter')
        projects = '[' + ', '.join(meta['projects']) + ']'
        message = ''
        if submitter:
            message = "Submitter: %s\n" % submitter

        message += "Comments: %s \nGit project: %s\nTag: %s\nCommit: %s" \
            % (comment or "submission %s" % str(name),
              projects,
              meta['git_tag'],
              commit)

        # Create SR
        reqid = build.create_sr(project, build.get_package_list(project),
                              str(meta['obs_target_prj']), message=str(message))
        print 'created SR %s' % reqid

        # and immediately set its state
        message = "SR %s is set to %s state. %s" % (reqid, state, comment)
        build.set_sr_state(reqid, state=state,
                         message=message, force=True)
        print 'set SR state to', state

    # delete submit group
    if submission.startswith('submitgroup'):
        build.cleanup(get_project_by_name(build, submission, target)[0],
                      "Submission %s has been %s" % (submission, state))


def main():
    """Script entry point."""
    build = BuildService(os.getenv("OBS_API_URL"),
                         os.getenv("OBS_API_USERNAME"),
                         os.getenv("OBS_API_PASSWD"))

    action = os.getenv("action")
    target_project = os.getenv("target_project")
    submission = os.getenv("submission")
    comment = os.getenv("comment")
    package = os.getenv("package")
    if submission and comment:
        if action in ("accept", "accepted", "reject", "declined"):
            state = "accepted" if action == "accept" or action == "accepted" else "declined"
            print "Submission %s has been %sed" % (submission, action)
            prj = get_project_by_name(build, submission, target_project)[0]
            if build.is_lock_project(prj):
                build.set_unlock_project(prj, comment)

            return accept_or_reject(build, submission, state,
                                    target_project, comment)
        elif action == "rebuild":
            prj, meta = get_project_by_name(build, submission, target_project)
            packages = [os.path.basename(path) for path in meta['projects']]
            if package:
                if package not in packages:
                    raise LocalError("Package %s doesn't exist in "
                                     "submission %s" % (package, submission))
                packages = [package]
            for pkg in packages:
                print "triggered rebuild for %s/%s" % (prj, pkg)
                build.runservice(prj, pkg)
            print "Submission %s has been rebuilt" % submission
        elif action == "remove":
            prj = get_project_by_name(build, submission, target_project)[0]
            if build.is_lock_project(prj):
                build.set_unlock_project(prj, comment)
            build.delete_project(prj, force=True, msg=comment)
            print "Submission %s has been removed" % submission
        elif action in ("lock", "unlock"):
            prj = get_project_by_name(build, submission, target_project)[0]
            if action == "lock":
                build.set_lock_project(prj)
            elif action == "unlock":
                comment = "Comments: submission %s \n" \
                           % (submission)
                build.set_unlock_project(prj, comment)
            else:
                print "exception"
            print "Submission %s has been %sed" % (submission, action)
        elif action in ("enable", "disable"):
            prj = get_project_by_name(build, submission, target_project)[0]
            status = "disable" if action == "disable" else "enable"
            build.set_global_flag("build", status, prj)
            print "Submission %s has been %sed" % (submission, action)
        else:
            raise LocalError("Unsupported action: '%s'" % action)
    elif not submission:
        raise LocalError("Submision is not specified")
    else:
        raise LocalError("Comment is not specified")

if __name__ == '__main__':
    try:
        reload(sys)
        # pylint: disable=E1101
        # reload(sys) fix: Module 'sys' has no 'setdefaultencoding' member
        sys.setdefaultencoding('utf-8')
        # pylint: enable=E1101
        sys.exit(main())
    except LocalError, err:
        print >> sys.stderr, "Error: %s" % str(err)
        sys.exit(1)

