#!/usr/bin/python2.3

# Copyright 2003-2005 Iustin Pop
#
# This file is part of cfvers.
#
# cfvers 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.
#
# cfvers is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with cfvers; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

# $Id: cfvadmin 222 2005-10-30 12:58:22Z iusty $

import cfvers
import cfvers.cmd
import mx.DateTime
try:
    from optparse import OptionParser, OptionGroup
except ImportError:
    from optik import OptionParser, OptionGroup
    
import os, os.path
import sys
import types

class CLI(object):
    def __init__(self):
        commands = {
            'init': (self.cmd_init, "Initializes the repository (do it only ONCE!)", False),
            'info': (self.cmd_info, "Display informations about the areas present", True),
            'create': (self.cmd_create, "Creates a new area", True),
            }
        self.curr_cmd = "<command>"
        self.usage="usage: %prog [global options] command [command options and arguments]\nwhere command is one of\n"
        l = commands.keys()
        l.sort()
        for i in l:
            self.usage += "    %-10s %s\n" % (i, commands[i][1])
        self.usage += "\nGlobal options:"
        self.commands = commands
    
    def get_scp(self, earg):
        """Returns a sub-command parser"""
        op = OptionParser(version=cfvers.cmd.CLIScript.get_version(),
                          usage="%%prog [global options] %s [options] " \
                          "%s\nFor global options, see %%prog --help" \
                          % (self.curr_cmd, earg))
        return op

    def prompt_func(self, key):
        prompt = "Please enter the %s: " % key
        if "password" in key:
            value = getpass.getpass(prompt)
        else:
            value = raw_input(prompt)
        return value

    def main(self, argv):
        op = OptionParser(version=cfvers.cmd.CLIScript.get_version(),
                          usage=self.usage)
        op.disable_interspersed_args()

        op.add_option("--local", dest="server_type",
                      action="store_const", const="local",
                      help="connect locally (not through the server)")
        op.add_option("--remote", dest="server_type",
                      action="store_const", const="remote",
                      help="connect through the server")
        ogl = OptionGroup(op, "Local options")
        ogl.add_option("--rtype", dest="repo_meth",
                       type="choice", choices=('postgresql', 'sqlite'),
                       help="repository type")
        ogl.add_option("--rdata", dest="repo_data",
                       type="string",
                       help="repository connect information")
        op.add_option_group(ogl)

        ogr = OptionGroup(op, "Remote options")
        ogr.add_option("-s", "--server", dest="host",
                       help="the host to connect to",
                       type="string", default=None,
                       metavar="HOSTNAME")

        ogr.add_option("-p", "--port", dest="port",
                       help="the port on the server",
                       type="int", default=None,
                       metavar="PORT")

        ogr.add_option("-u", "--username", dest="username",
                       help="the username for authentication to the server",
                       type="string", default=None,
                       metavar="USERNAME")
        ogr.add_option("-P", "--PROMPT", dest="do_prompt",
                       help="prompt for password",
                       action="store_true", default=False,
                       )
        op.add_option_group(ogr)

        (options, args) = op.parse_args(argv)
        options.area = None
        if len(args) == 0:
            op.print_help()
            return
        command = args.pop(0)
        if not command in self.commands:
            print "Unknown command %s" % command
            op.print_help()
            return
        func, descr, openflag = self.commands[command]
        try:
            self.cmdi = cfvers.cmd.AdminCommands(options, self.prompt_func, do_connect=openflag)
        except cfvers.ConfigException, e:
            print >>sys.stderr, "Error: your configuration is invalid.\nError message: %s." % e
            return
        except cfvers.RepositoryException, e:
            print >>sys.stderr, "Error: repository opening failed.\nError message: %s." % e
            return
        except cfvers.CommException, e:
            print >>sys.stderr, "Error: communication error.\nError message: %s" % (" ".join(e.args),)
            return
        except Exception, e:
            print >>sys.stderr,"Error while initializing: %s" % e
            raise
            return
        self.curr_cmd = command
        try:
            func(options, args)
        finally:
            self.cmdi.close()
        return
        
    def cmd_init(self, options, args):
        """Initialize the local repository"""
        op = self.get_scp("")
        op.add_option("--force", dest="force",
                      help="drop existing schema first",
                      action="store_true", default=False,
                      )
        op.add_option("--skip-data", dest="doarea",
                      help="skip data creation",
                      action="store_false", default=True,
                      )
        (cmdoptions, cmdargs) = op.parse_args(args)
        try:
            self.cmdi.init_repo(cmdoptions)
        except cfvers.ConfigException, e:
            print >>sys.stderr, "Error: your configuration is invalid.\nError message: %s." % e
            return
        except cfvers.RepositoryException, e:
            print >>sys.stderr, "Error: repository opening failed.\nError message: %s." % e
            return
        return

    def cmd_create(self, options, args):
        """Creates a new area"""
        op = self.get_scp("area_name")
        op.add_option("-d", "--description", dest="description",
                      help="area description",
                      type="string", 
                      metavar="TEXT")
        op.add_option("-p", "--rootpath", dest="root",
                      help="filesystem root of the area [/]",
                      type="string", default="/",
                      metavar="PATH")
        
        (cmdoptions, cmdargs) = op.parse_args(args)
        if len(cmdargs) != 1:
            print >>sys.stderr, "You must give the area name!!"
            return
        try:
            self.cmdi.create_area(cmdoptions, cmdargs[0])
        except cfvers.OperationError, e:
            print >>sys.stderr, "Error while creating area: %s" % str(e)
        return

    def cmd_info(self, options, args):
        """Show informations about the local repository"""
        op = self.get_scp("")
        (cmdoptions, cmdargs) = op.parse_args(args)
        p = self.cmdi.portal
        arealist = p.getAreas()
        print "Local repository has %d area(s)" % len(arealist)
        for a in arealist:
            print "-" * 25
            print "Name: %s" % a.name
            print "Created at %s %s" % (a.ctime.localtime().strftime("%Y-%m-%d %T"), a.ctime.tz)
            print "Root path: %s" % a.root
            print "Description: %s" % a.description
            if a.revno is None:
                print "No revisions in this area"
            else:
                print "Revision number: %d" % a.revno
                print "Number of items: %d" % a.numitems
        return
    

if __name__ == "__main__":
    cli = CLI()
    cli.main(sys.argv[1:])
