#!/usr/bin/python
"""Bugz

Bugz is the class that takes a username, and a query and submits that to 
bugzilla.mozilla.org or the specified host and summarizes the results in a
number. 

-Gagzilla <saksenagagan@NOSPAM.netscape.net> 08/27/00 

"""

import os
import string
import re
from gagz.utils import *
from gagz.bugz import *
from gagz.bugz.konst import *
from ConfigParser import *
from httplib import HTTP

#Exceptions
class NoSuchQueryError:
    """A query was requested which doesn't exist"""
    def __init__(self, qi, msg=''):
        self._msg='queryid: %d %s' % (qi, msg)
        self.queryid = qi
    def __repr__(self):
        return self._msg

class Query:
    """A simple struct/class for query string and its associated description"""
    def __init__(self, i, q, d, s):
        self.id=i
        self.query = q
        self.desc = d
        self.short = s

class Bugz:
    """Bugz is the main class for doing bugzilla queries"""

    def __init__(self, host='bugzilla.mozilla.org'):
        """Constructor"""

        self.host=host
        self.queries=[]
        self.loadqueries()
        self.saveLastQuery = None

    def loadqueries(self, cfg=ConfigParser()):
        """read in the available queries"""

        queryFile = kSiteInstallationDir +  kQueriesFile
        if not os.path.isfile(queryFile):
            FatalError(queryFile + " is missing!")
        try:
            cfg.read(queryFile)
            allq=cfg.get('QUERIES','runqueries')
            for qs in string.split(allq):
                tempQuery = None
                try:
                    tempQuery = cfg.get(qs, 'query')
                    # skip over possible http://hostname/ 
                    # assuming the query is wellformed http
                    if tempQuery[:7]=='http://':
                        tempQuery = tempQuery[string.find(tempQuery,'/',7):]
                    # The query must have gagan in it, else its a bad query :)
                        string.index(tempQuery, 'gagan')
                except ValueError:
                    Warning( 'Query doesn''t contain gagan! skipping it...')
                    continue
                except NoSectionError:
                    Warning(queryFile + ' is missing referenced section(%s)!' %
                        qs)
                    continue
          
                # Make a new query structure
                q = Query(cfg.getint(qs,'id'),
                    tempQuery,
                    cfg.get(qs,'desc'),
                    cfg.get(qs, 'shortdesc'))
                # and add it...
                self.queries.append(q)

        except ParsingError:
            FatalError(queryFile + ' parsing problems!')
        except NoOptionError:
            FatalError(queryFile + 
            ' missing runqueries(in QUERIES) or missing query,desc,id!')

    def savequeries(self):
        """save the set of queries we used here... """

        queryFile = kSiteInstallationDir + kQueriesFile
        f = open(queryFile, 'w')
        if not f:
            FatalError('failed to open queryfile for writing!')
        f.write("""# AUTOGENERATED Do not edit!
# Use gagz.bugz.Bugz to modify this file!\n\n""")
        f.write('[QUERIES]\n')
        f.write('runqueries: %s\n\n' % string.join(
            map(lambda x: x.short, self.queries)))

        for k in self.queries:
            f.write("[%s]\nid: %d\nquery: %s\ndesc: %s\nshortdesc: %s\n\n" % 
                (k.short, k.id, k.query, k.desc, k.short))

        f.close()

    def parseForBugsFound(self, f):
        """In the specified file, search for '%n bugs found' and return that
number. It also would parse each line (instead of returning as soon as
conclusive number is found)  and in case of saveLastQuery save the relevant
lines in the lastquery file."""

        if self.saveLastQuery:
            cache = open(self.saveLastQuery, 'w')
            worthSomething = re.compile('show_bug.cgi\?')

        debug_dump = open("/tmp/debug_dump", 'w')

        line = f.readline()
        if line == "":
            return -1
        pattern = re.compile('(\d+) bugs found.|Zarro Boogs found.');
       
        count = ''
        while line != "":
            if line != "\n": debug_dump.write(line)
            m = pattern.search(line)
            if self.saveLastQuery and worthSomething.search(line):
                cache.write(line)
            if m:
                if m.group(1):
                    count = m.group(1)
                else:
                    count = '0'
            line = f.readline()
        debug_dump.close()
        if self.saveLastQuery:
            cache.close()
        return count


    def query(self, user, queryid):
        """Submit the specified query to the server."""

        h = HTTP(self.host)
        h.putrequest('GET', self.querystring(user,queryid))
        h.putheader('Host',self.host)
        h.putheader('User-Agent', kUserAgent)
        # the magic to only pull the relevant columns...
        h.putheader('Cookie',
'SPLITHEADER=0; COLUMNLIST=owner keywords target_milestone status_whiteboard;')
        h.putheader('Accept', 'text/*')
        h.endheaders()

        errcode, errmsg, headers = h.getreply()
        if errcode!=200:
            Warning("Bugzilla query failed-- %d %s" % (errcode, errmsg))
            return;

        count= self.parseForBugsFound(h.getfile())
        return count

    def querystring(self, user, queryid):
        """Return the querystring associated with the specified id and also
        substitute gagan with the specified user"""

        for q in self.queries: 
            if q.id == queryid:
                return string.replace(q.query, 'gagan', user)
        else:
            raise NoSuchQueryError(queryid)

    def querylink(self, user, queryid):
        return 'http://' + self.host + self.querystring(user, queryid)

def test(user='gagan'):
    """Test this module!"""

    b = Bugz()
    print '%s has %s bugs' % (user, b.query(user, 1))

if __name__ == '__main__':
    test()
