#!/usr/bin/python

import sys
import getpass
import log_picker

import log_picker.argparser as argparser
from log_picker.argparser import ArgError
import log_picker.archiving as archiving
from log_picker.archiving import NoFilesArchivationError
import log_picker.sending as sending
from log_picker.sending import SenderError
import log_picker.logmining as logmining


class ApplicationScope(object):
    """Application configuration class."""
    
    def __init__(self, parser_options):       
        self.bug_comment = parser_options.ensure_value('bug_comment', None)
                        
        self.bug_id = parser_options.ensure_value('bug_id', None)
        self.login = parser_options.ensure_value('login', None)
        self.password = None
        
        self.smtp_server = parser_options.ensure_value('smtp_addr', None)
        self.from_addr = parser_options.ensure_value('from_addr', None)
        self.to_addr = []
        if parser_options.ensure_value('to_addr', None):
            self.to_addr = [parser_options.to_addr]
        self.host = parser_options.ensure_value('host', None)
        self.path = parser_options.ensure_value('path', None)
        
        # sender
        self.sender = parser_options.ensure_value('sender', None)
               
        # miners
        self.miners = logmining.ALL_MINERS


class Injector(object):
    """Main factory class."""

    @staticmethod
    def inject_main_helper(scope):
        logpicker = Injector.inject_logpicker(scope)
        return MainHelper(logpicker)
    
    @staticmethod
    def inject_logpicker(scope):
        sender = Injector.inject_sender(scope)
        archivator = Injector.inject_archivator(scope)
        return log_picker.LogPicker(archive_obj=archivator, sender_obj=sender, 
                                    miners=scope.miners)
    
    @staticmethod
    def inject_sender(scope):
        if scope.sender == sending.RHBZ:
            sender = sending.RedHatBugzilla()
            sender.set_bug(scope.bug_id)
            sender.set_comment(scope.bug_comment)
            sender.connect_and_login(scope.login, scope.password)
            return sender
        if scope.sender == sending.EMAIL:
            sender = sending.EmailSender(scope.from_addr, scope.to_addr, 
                                         scope.smtp_server)
            sender.set_comment(scope.bug_comment)
            return sender
        if scope.sender == sending.STRATA:
            sender = sending.StrataSender()
            sender.set_login(scope.login, scope.password)
            sender.set_case_number(scope.bug_id)
            return sender
        if scope.sender == sending.SCP:
            sender = sending.ScpSender()
            sender.set_login(scope.login)
            sender.set_path(scope.path)
            sender.set_host(scope.host)
            return sender
        if scope.sender == sending.FTP:
            sender = sending.FtpSender()
            sender.set_login(scope.login, scope.password)
            sender.set_host(scope.host)
            return sender
        if scope.sender == sending.LOCAL:
            sender = sending.LocalSender()
            sender.set_path(scope.path)
            return sender
            
        raise Exception("Unknown sender type.")
    
    @staticmethod
    def inject_archivator(scope):
        return archiving.Bzip2Archive()
    

class MainHelper(object):
    """Main application class."""
    
    def __init__(self, logpicker):
        self.picker = logpicker
    
    def run(self):
        self.picker.getlogs()
        self.picker.create_archive()
        self.picker.send()
        print "Successfully completed!"



if __name__ == "__main__":
    
    # Argument parsing
    try:
        options = argparser.ArgParser().parse()
    except (ArgError) as e:
        sys.stderr.write("Argument error: %s\n" % e)
        sys.exit(1)
        
    # Application scope
    scope = ApplicationScope(options)
    if scope.sender == sending.RHBZ or scope.sender == sending.STRATA or \
       (scope.sender == sending.FTP and scope.login):
        scope.password = getpass.getpass("Password: ")
    
    # Application
    try:
        app = Injector.inject_main_helper(scope)
        app.run()
    except (NoFilesArchivationError):
        sys.stderr.write("Nothing to report.\n")
        sys.exit(0)
    except (SenderError) as e:
        sys.stderr.write("Error: %s\n" % e)
        sys.exit(1)
    
