#!/usr/bin/env python

# Written by Henrik Nilsen Omma
# (C) Canonical, Ltd. Licensed under the GPL

import os
import sys
import urllib
import re
import time

try:
    from commandLine import commandLine
    from infoFiles import InfoFiles
    import connector as Connector
    import utils
    import config
    import bzrutils
    import output
    import statistic
except:
    from bugHelper.commandLine import commandLine
    from bugHelper.infoFiles import InfoFiles
    import bugHelper.config as config
    import bugHelper.bzrutils as bzrutils
    import bugHelper.output as output
    import bugHelper.statistic as statistic
    import launchpadbugs.connector as Connector
    import bugHelper.utils as utils

def main():
    conf = config.Config("~/.bughelper/config")
    cl = commandLine()
    
    Bug = Connector.ConnectBug()
    BugList = Connector.ConnectBugList()
    cookie = None
    try:
        cookie = cl.options.cookie
    except:
        try:
            cookie = os.path.expanduser(config.cookie)
        except:
            if cl.options.debug:
                print >> sys.stderr, "No cookie-file found"
    if cookie:
        BugList.authentication=cookie
        Bug.authentication=cookie
        
    try:
        out = output.Output("bughelper",cl.options.format,cl.options.file)
    except output.StyleNotFound, e:
        print >> sys.stderr, e
        sys.exit(1)
    out.print_header()
    start = time.time()
    if cl.options.gen_config:
        sys.exit(0)

    # TODO: Where to print messages like 'Now on revision xx'
    # or 'No revisions to pull.'
    try:
        (bzrinfo,bzrerr) = bzrutils.update_packages_data(conf.packages_dir, conf.update_interval)
        # print (bzrinfo,bzrerr)
    except bzrutils.BzrError, e:
        out.error(e)
    if not cl.options.try_only_clue:
        files = InfoFiles(set((conf.packages_dir, conf.local_packages_dir)))
    else:
        files = InfoFiles(set())
        files.add_simple_clue(cl.options.try_only_clue[0], 
                              cl.options.try_only_clue[1],
                              cl.options.try_only_clue[2])
    if cl.options.try_clue:
        # load existing clues first
        files.get_info_file(cl.options.try_clue[0], cl.options.verbose)
        files.add_simple_clue(cl.options.try_clue[0], 
                              cl.options.try_clue[1],
                              cl.options.try_clue[2])
    if cl.options.bugnr:
        bl = set([cl.options.bugnr])
    else:
        if not cl.options.url and not cl.options.sourcepackage:
            cl.parser.print_usage()
            sys.exit(1)
            
        BugList.set_filter(Bug_cls=Bug, **vars(cl.options))
        
        if not cl.options.url:
            cl.options.url = \
                "https://bugs.launchpad.net/distros/ubuntu/+source/%s/+bugs?%s" % \
                    (cl.options.sourcepackage, BugList.urlopt)
        else:
            try:
                cl.options.url = BugList.get_modified_url(cl.options.ignore_conflicts)
            except ValueError, e:
                print >> sys.stderr, e
                sys.exit(1)

        if cl.options.no_duplicates:
            m = re.search('^(<|>){0,1}([0-9]+$)', cl.options.no_duplicates)
            if not m:
                cl.parser.print_usage()
                sys.exit(1)
            if m.group(1) == "<" :
                no_duplicates = lambda x: x < int(m.group(2))
            elif m.group(1) == ">" :
                no_duplicates = lambda x: x > int(m.group(2))
            else:
                no_duplicates = lambda x: x == int(m.group(2))
        
        try:
            bl = BugList(cl.options.url).filter()
        except BugList.Error.LPUrlError, e:
            x = " Maybe package '%s' does not exist in ubuntu." %cl.options.sourcepackage if cl.options.sourcepackage else ""
            print >> sys.stderr, "Error while parsing '%s': %s.%s" %(cl.options.url, e, x)
            sys.exit(1)
            
        if cl.options.upstream and cl.options.sourcepackage:
            l = None
            try:
                l = BugList("http://launchpad.net/%s/+bugs?%s" % (cl.options.sourcepackage, BugList.urlopt)).filter()
            except BugList.Error.LPUrlError, e:
                if cl.options.debug:
                    print >> sys.stderr, "There is no product <%s> in launchpad.net" %cl.options.sourcepackage
            if l:
                bl += l
                
        if cl.options.sourcepackage:
            path = os.path.expanduser(os.path.join(conf.attachments_cache, 
                                                   cl.options.sourcepackage))
            utils.remove_obsolete_attachments(path, bl)

    if not bl:
        out.info("No bugs found.")
        out.print_footer()
        sys.exit(1)
    count_bugs = 0
    all_bugs = []
    if cl.options.attachments:
        Bug.attachment_path = conf.attachments_cache
    for bugNum in bl:
        b = bugNum
        if str(type(b)) != "Bug":
            try:
                b = Bug(bugNum)
            except Bug.Error.LPUrlError, e:
                if cl.options.debug:
                    print >> sys.stderr, "This error occurs while getting #%s: %s" %(bugNum, e)
                continue
        if cl.options.no_duplicates:
            if not no_duplicates(len(b.duplicates)):
                continue
            count_bugs += 1
        displayclues = dict()
        info_file = files.get_info_file(b.sourcepackage, cl.options.verbose)
        if not str(bugNum) in info_file.dontlist:
            collected_clues = set()
            if cl.options.heuristic and (not b.sourcepackage or \
                                         not info_file.clues):
                all_files = files.get_available_clue_files()
                for f in all_files:
                    info_file = files.get_info_file(b.sourcepackage, \
                                                    cl.options.verbose)
                    collected_clues.update(info_file.clues)
                    collected_clues.update(info_file.inherited_clues)
            if info_file.clues:
                collected_clues.update(info_file.clues)
                collected_clues.update(info_file.inherited_clues)
                for clue in collected_clues:
                    try:
                        if info_file.clue_matches(clue, b, 
                                              cl.options.case_sensitive):
                            displayclues[clue.info] = set()
                    except AttributeError, e:
                        if cl.options.debug:
                            print >> sys.stderr, e
                    if cl.options.attachments:
                        for a in b.attachments.filter(lambda a: re.match("^.*[^\.gz]$", a.lp_filename)):
                            try:
                                if info_file.clue_matches(clue, a):
                                    if not displayclues.has_key(clue.info):
                                        displayclues[clue.info] = set()
                                    displayclues[clue.info].add(a.url)
                            except AttributeError, e:
                                if cl.options.debug:
                                    print >> sys.stderr, e
                if displayclues:
                    out.print_item({"bug": b, "clue" : displayclues})
                    all_bugs.append(b)
    if cl.options.no_duplicates and not count_bugs:
        out.info("No bugs found.")
        out.print_footer()
        sys.exit(1)
    
    footer_opt = {}
    if cl.options.footer:
        o = list(cl.options.footer)
        if "s" in o:
            footer_opt["statistic"] = statistic.summary(all_bugs)
        if "t" in o:
            footer_opt["time"] = {
                "time": time.strftime("%a, %d %b %Y %H:%M:%S %Z"),
                "duration" : "%i" %(time.time() - start)}
    out.print_footer(footer_opt)

if __name__ == "__main__":
    main()

