#! /usr/bin/python
# -*- python -*-
# querybts - Examine the state of a debbugs server
#   Written by Chris Lawrence <lawrencc@debian.org>
#   (C) 1999-2008 Chris Lawrence
#   Copyright (C) 2008-2009 Sandro Tosi <morph@debian.org>
#
# This program is freely distributable per the following license:
#
##  Permission to use, copy, modify, and distribute this software and its
##  documentation for any purpose and without fee is hereby granted,
##  provided that the above copyright notice appears in all copies and that
##  both that copyright notice and this permission notice appear in
##  supporting documentation.
##
##  I DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
##  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL I
##  BE LIABLE FOR ANY SPECIAL, 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.
#
# Version ##VERSION##; see changelog for revision history
#
# $Id: querybts,v 1.7.2.3 2008-04-18 05:38:27 lawrencc Exp $

import sys
import os
import getopt
import re

from reportbug import utils
from reportbug.exceptions import (
    UINotImportable,
    NoPackage, NoBugs, NoReport, NoNetwork,
    )
from reportbug import debianbts
from reportbug import urlutils

from reportbug.ui import AVAILABLE_UIS

import reportbug.ui.text_ui as ui
ui_mode = 'text'

from reportbug import VERSION_NUMBER

VERSION = "querybts %s" % VERSION_NUMBER

USAGE = ("querybts - Examine the state of a debbugs server.\n\n"
         "Usage: querybts [options] {<package> | <report number> [report2] ...}\n"
         "Supported options (see man page for long forms):\n"
         "  -A: Browse archived bugs.\n"
         "  -b: Display a bugs list for the given package.\n"
         "  -B: Specify an alternate debbugs BTS. *\n"
         "  -h: Display this help message.\n"
         "  -s: Query for source packages rather than binary packages.\n"
         "  -v: Show the version number of this program.\n"
         "  -w: Use a web browser instead of the internal interface.\n"
         "\nOptions marked * take the word 'help' to list allowed options."
         )

def main():
    system = 'debian'
    archived = False
    http_proxy = interface = ''
    use_browser = source = False
    mirrors = None
    mbox = False
    buglist = False

    args = utils.parse_config_files()
    for option, arg in args.items():
        if option == 'system':
            system = arg
        elif option == 'mirrors':
            mirrors = arg
        elif option == 'interface':
            interface = arg
        elif option == 'http_proxy':
            http_proxy = arg

    try:
        (opts, args) = getopt.getopt(
            sys.argv[1:], 'AB:bhlmsuvw', ['help', 'version',
                                        'bts=', 'web', 'mbox',
                                        'archive', 'source',
                                        'http_proxy=', 'proxy=',
                                        'ui=', 'interface=',
                                        'buglist'])
    except getopt.error, msg:
        print msg
        sys.exit(1)

    for option, arg in opts:
        if option in ('-h', '--help'):
            print USAGE
            return
        elif option in ('-v', '--version'):
            print VERSION
            return
        elif option in ('--proxy', '--http_proxy'):
            http_proxy = arg
        elif option in ('-m', '--mbox'):
            mbox = True
        elif option in ('-b', '--buglist'):
            buglist = True
        elif option in ('--archive', '-A'):
            archived = True
        elif option in ('-s', '--source'):
            source = True
        elif option in ('-u', '--ui', '--interface'):
            if arg in AVAILABLE_UIS.keys():
                interface = arg
            elif arg == 'help':
                print 'Allowed arguments to --ui:\n'
                for k in AVAILABLE_UIS.keys(): print ' %s: %s' % (k, AVAILABLE_UIS[k])
                sys.exit(0)
            else:
                print "Ignoring unknown user interface %s\n" % arg
        elif option in ('-w', '--web'):
            use_browser = True
        elif option in ('-B', '--bts'):
            if arg in debianbts.SYSTEMS.keys():
                if debianbts.SYSTEMS[arg].get('btsroot'):
                    system = arg
                else:
                    print "Queries not supported for %s BTS." % arg
                    return
            elif arg == 'help':
                print 'Permitted arguments to --bts:'
                names = debianbts.SYSTEMS.keys()
                names.sort()
                for bsys in names:
                    if debianbts.SYSTEMS[bsys].get('btsroot'):
                        print ' %-11.11s %s' % \
                              (bsys, debianbts.SYSTEMS[bsys]['name'])
                return
            else:
                print "Ignoring unknown BTS server %s." % arg

    sysinfo = debianbts.SYSTEMS[system]
    if len(args) == 0:
        print "Please specify a package or one or more bug numbers."
        print "Note: most shells consider # a comment character; however, a"
        print "leading # is not needed to specify a bug by number."
        sys.exit(1)

    if use_browser:
        if use_browser and buglist:
            print "--web and --buglist can't work together, exiting."
            sys.exit(1)
        package = args[0]
        m = re.match('^#?(\d+)$', package)
        if m:
            num = int(m.group(1))
            url = debianbts.get_report_url(system, num, mirrors, archived)
        else:
            url = debianbts.get_package_url(system, package, mirrors, source, archived)
        urlutils.launch_browser(url)
        return

    if interface:
        global ui, ui_mode
        iface = '%(interface)s_ui' % vars()
        try:
            lib_package = __import__('reportbug.ui', fromlist=[iface])
            ui = getattr(lib_package, iface)
            ui_mode = interface
        except UINotImportable, msg:
            ui.long_message('*** Unable to import %s interface: %s '
                            'Falling back to %s interface.\n',
                            interface, msg, ui_mode)
            print
    ui.initialize ()

    if mbox:
        if mbox and buglist:
            print "--mbox and --buglist can't work together, exiting."
            sys.exit(1)
        for bugnum in args:
            package = bugnum
            m = re.match('^#?(\d+)$', bugnum)
            if not m:
                mboxbuglist = []
                mboxbuglist = ui.handle_bts_query(package, system, mirrors, http_proxy,
                                    queryonly=True, title=VERSION, archived=archived,
                                    source=source, mbox=mbox)
                for num in mboxbuglist:
                    url = debianbts.get_report_url(system, num, archived, mbox=True)
                    try:
                        report = urlutils.open_url(url)
                        sys.stdout.write(report.read())
                    except urlutils.urllib2.URLError, ex:
                        print >> sys.stderr, "Error while accessing mbox report (%s)." % ex
            else:
                num = int(m.group(1))
                url = debianbts.get_report_url(system, num, archived, mbox=True)
                try:
                    report = urlutils.open_url(url)
                    sys.stdout.write(report.read())
                except urlutils.urllib2.URLError, ex:
                    print >> sys.stderr, "Error while accessing mbox report (%s)." % ex
                    sys.exit(1)
        return


    reportre = re.compile(r'^#?(\d+)$')
    try:
        if len(args) > 1:
            bugs = []
            for report in args:
                match = reportre.match(report)
                if match:
                    bugs.append(int(match.group(1)))
            package = bugs
            if not bugs:
                raise ui.NoBugs
        else:
            package = args[0]
            match = reportre.match(package)
            if match:
                report = int(match.group(1))
                return ui.show_report(report, system, mirrors,
                                      http_proxy, queryonly=True,
                                      title=VERSION,
                                      archived=archived)
        ui.handle_bts_query(package, system, mirrors, http_proxy,
                            queryonly=True, title=VERSION, archived=archived,
                            source=source, buglist=buglist)
    except NoPackage:
        ui.long_message('Package appears not to exist in the BTS.\n')
    except NoBugs:
        ui.long_message('No bug reports found.\n')
    except NoReport:
        ui.long_message('Exiting.\n')
    except NoNetwork:
        ui.long_message('Cannot connect to network.\n')

if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print "querybts: exiting due to user interrupt."
    except debianbts.Error, x:
        print 'error accessing BTS: '+str(x)
    except SystemExit:
        pass
    except:
        raise
