"""
This is the Main Controller.
It starts the server, shows splash screen and cleans up afterwards.
MainController is imported and run by the 'pycocuma' executable script.
"""
#  Copyright (C) 2004  Henning Jacobs <henning@srcco.de>
#
#  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; either version 2 of the License, or
#  (at your option) any later version.
#
#  $Id: MainController.py 142 2005-09-13 21:16:23Z henning $

import Preferences
import broker
from __version__ import __version__
from MainModel import MainModel

CMDLINE_HELP = """\
PyCoCuMa: Pythonic Contact and Customer Management version %s
Usage: pycocuma [options] [connection-string]

   connection-string  addressbook filename / server url
   -h   or --help     show this help
   -c   or --config   location of configuration file (default: ~/.pycocuma)
           --noconf   do not save configuration / preferences
   -t   or --type     connection type: xmlrpc or file (default: file)
           --finder   open QuickFinder
           --import   import from file/stdin (-) (e.g. vcard:/tmp/John.vcf)
           --export   export to file or stdout (e.g. latex:-)

Examples:
   pycocuma --type=xmlrpc http://localhost:8810
   pycocuma --config=/tmp/pycocumatest.conf --type=file ./addressbook.vcf
   pycocuma --import=csv:myaddresses.csv

See homepage: http://www.srcco.de/pycocuma/""" % __version__

class MainController:
    def __init__(self, nogui=False, nouserpref=False):
        # Don't create any GUI-windows (e.g. MainView):
        self.nogui = nogui
        # Start QuickFinder only:
        self.startquickfinder = False
        # Do not load nor save preferences to ~/.pycocuma:
        self.nouserpref = nouserpref
        # import from this file
        self.importfile = None
        # export to this file
        self.exportfile = None
        optlist, args, preffile = self.parseCommandLineOptions()
        # Load Preferences:
        if not nouserpref:    
            Preferences.Load(preffile)
        self.applyCommandLineOptions(optlist, args)
        # importing and exporting disables the GUI:
        if self.importfile or self.exportfile:
            self.nogui = True
        # Display Splash-Screen:
        self.splash = None
        if not self.nogui:
            from SplashScreen import SplashScreen
            # The Tk-Root will be created by SplashScreen:
            self.splash = SplashScreen()
            self.splash.show()
        import locale    
        locale.setlocale(locale.LC_ALL, '')
        self.model = MainModel()
        if not self.nogui:
            tkroot = None
            if self.splash: tkroot = self.splash.tkroot
            if self.startquickfinder:
                from QuickFinder import QuickFinder
                self.view = view = QuickFinder(__version__, self.model, tkroot)
            else:    
                from MainView import MainView
                self.view = view = MainView(__version__, self.model, tkroot)
                                        
    def parseCommandLineOptions(self):
        "Parse Command-Line Options"
        import getopt, sys
        try:
            optlist, args = getopt.getopt(sys.argv[1:], "c:ht:",
                ['help', 'config=', 'noconf', 'type=', 'finder',
                 'import=', 'export='])
        except getopt.GetoptError, msg:
            print "ERROR: " + str(msg)
            self.showCommandLineHelp()
        preffile = None    
        for key, val in optlist:
            if key == "-c" or key == "--config":
                preffile = val
        return (optlist, args, preffile)
    
    def applyCommandLineOptions(self, optlist, args):
        "Overwrite Preferences with command-line options"
        if len(args) >= 1:
            Preferences.set("client.connection_string", args[0])
            Preferences.set("client.connection_type", 'file')
        for key, val in optlist:
            if key == "-h" or key == "--help":
                self.showCommandLineHelp()
            elif key == "--noconf":
                self.nouserpref = True
            elif key == "--finder":
                self.startquickfinder = True
            elif key == "--import":
                self.importfile = val
            elif key == "--export":
                self.exportfile = val
            # Command Line Arguments override Preferences:
            elif key == "-t" or key == "--type":
                Preferences.set("client.connection_type",val)
                
    def showCommandLineHelp(self):
        "Print Help Screen and Exit"
        import sys
        print CMDLINE_HELP
        sys.exit(0)
        
    def startServer(self):
        "start the XML-RPC Server"
        import os, sys
        # Where to look for the server executable:
        serverpaths = [
            os.path.dirname(sys.argv[0])+'/pycocuma-server',
            'pycocuma-server',
            'CoCuMa_Server.py'
            ]
        for path in serverpaths:
            serverfilename = path
            if os.access(serverfilename, os.R_OK):
                break
        # Run our Server Daemon:
        os.spawnv(os.P_NOWAIT, sys.executable,
            [sys.executable, serverfilename,
            '-h', Preferences.get('server.listen_host'),
            '-p', Preferences.get('server.listen_port'),
            '-f', Preferences.get('server.addressbook_filename'),
            '-j', Preferences.get('server.calendar_filename')
            ])
    
    def doImport(self, filename):
        "Import into model from file or stdin"
        import converters, sys, os
        parts = filename.split(':')
        if len(parts) > 1:
            # format specified (e.g. vcard or csv)
            srcformat = parts[0]
            filename = parts[1]
        else:
            # try to guess by file extension
            root, ext = os.path.splitext(filename)
            if ext == "csv":
                srcformat = ext
            else:
                srcformat = "vcard"
        if filename == "-":
            # use StdIn:
            fd = sys.stdin
        else:
            # read file:
            fd = file(filename, 'rb')
        try:
            converters.importvcards(self.model, srcformat, fd, 'utf-8')
        finally:
            fd.close()
        
    def doExport(self, filename):
        "Export from model to file or stdout"
        import converters, sys, os
        parts = filename.split(':')
        if len(parts) > 1:
            # format specified (e.g. vcard or csv)
            dstformat = parts[0]
            filename = parts[1]
        else:
            # try to guess by file extension
            root, ext = os.path.splitext(filename)
            if ext == "csv":
                dstformat = ext
            elif ext == "xml":
                dstformat = "xmlrdf"
            else:
                dstformat = "vcard"
        if filename == "-":
            # use StdOut:
            fd = sys.stdout
        else:
            # read file:
            fd = file(filename, 'wb')
        outfile = converters.EncodedFileWriter(fd, 'utf-8')
        try:
            converters.exportvcards(self.model, dstformat, outfile, 'utf-8')
        finally:
            fd.close()
            
    def Run(self):
        "Fire up the server and the client's main window"
        if Preferences.get("client.connection_type").lower() == "xmlrpc"\
          and Preferences.get("client.autostart_server").lower() == "yes": 
            self.startServer()
        if self.splash:
            self.splash.update("Connecting...") 
        self.model.Open(Preferences.get('client.connection_type'), Preferences.get('client.connection_string'))
        if not self.nogui:
            if self.splash:
                self.splash.destroy()
                self.splash = None
            self.view.tkroot.mainloop()
        if self.importfile:
            self.doImport(self.importfile)
        if self.exportfile:
            self.doExport(self.exportfile)
        if self.model.isConnected():
            Preferences.set('client.connection_type', broker.Request("Connection Type"))
            Preferences.set('client.connection_string', broker.Request("Connection String"))
            
    def CleanUp(self):
        "Close the connection to server and save user preferences"
        self.model.Close(final=1)
        if not self.nogui:
            self.view.tkroot.destroy()
        if not self.nouserpref:
            Preferences.Save()
