#!/usr/bin/python
# -*- coding: utf8 -*-
__version__ = "$Revision: 233 $ $Date: 2011-06-12 23:29:07 +0200 (dim. 12 juin 2011) $"
__author__  = "Guillaume Bour <guillaume@bour.cc>"
__license__ = """
	Mother, Application Server
	Copyright (C) 2010, Guillaume Bour <guillaume@bour.cc>

	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 3 of the License, or
	(at your option) any later version.

	This program 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 this program; if not, write to the Free Software Foundation, Inc.,
	51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA..
"""
import sys, os, os.path, sqlite3, traceback
from optparse import OptionParser

from twisted.internet       import reactor
from twisted.web            import server
from twisted.web.resource   import Resource

from mother                 import Mother, autoreload, config


# default settings values
defaults = {
	'conffile'      : '/etc/mother.cfg',
	'database'      : '/var/lib/mother/mother.db',
	'port'          : 8080,
	'accesslog'     : '/var/log/mother/access.log',
	'logfile'       : '/var/log/mother/mother.info',
	'loglevel'      : 'error',
}


# ----
foreground = True
if __name__ != '__main__':
	foreground = False
	# when started via twistd, argv contains twistd options, not ours
	print sys.argv
	sys.argv=[]

# 1. parse options
parser = OptionParser()
parser.add_option('-c', '--config-file', dest='conffile',
	default=defaults['conffile'],
	help='configuration file')
parser.add_option('-d', '--database'   , dest='database',
	default=defaults['database'],
	help='database URI')
parser.add_option('-p', '--port'       , dest='port',
	default=defaults['port'], type="int",
	help='listening port')
parser.add_option('-a', '--access-log' , dest='accesslog',
	default=defaults['accesslog'],
	help='application access log file')
parser.add_option('--log-file'         , dest='logfile',
	default=defaults['logfile'],
	help='application log file')
parser.add_option('-l', '--log-level'   , dest='loglevel',
	default=defaults['loglevel'],
	help='application log level')
parser.add_option('--plugins'          , dest='plugins',
	default=None,
	help='list of plugins to activate')
		
parser.add_option('--apps-list'        , dest='list',
	action='store_true', default=False,
	help='list installed apps')
parser.add_option('--apps-add'         , dest='add',
	action="store", type="str", 
	help='add new app', metavar='PATH')
parser.add_option('--apps-remove'      , dest='remove',
	action="store", type="str", 
	help='remove installed app', metavar='NAME|UUID')
parser.add_option('--status'           , dest='status', 
	action='store_true', default=False,
	help='list available plugins')
parser.add_option('--autoreload'       , dest='autoreload',
	action='store_true', default=False,
	help='autoreload application when changes detected')
		
(options, args) = parser.parse_args()

	# 2. load config
if not os.path.isfile(options.conffile):
	print "%s configuration file is not found." % options.conffile
	sys.exit(1)

cfg = config.Config(options.conffile)
for opt in parser.option_list:
	if opt.dest is None:
	    continue
		
	if not hasattr(cfg, opt.dest) or getattr(options, opt.dest) != opt.default:
		setattr(cfg, opt.dest, getattr(options, opt.dest))


if options.status:
	print "status"
	sys.exit(1)

try:
	mom = Mother(cfg)
except Exception, e:
	print e
	sys.exit(1)
		
if options.list:
	print "Plugins:"
	for plug in mom.list_plugins():
	    print " . %12s [active=%d, path=%s]" % (plug['name'], plug['active'],	plug['path'])
	sys.exit(0)

if options.add is not None:
	from mother.pluggable import Plugin

	appdir, appname = [(os.path.dirname(path), os.path.basename(path)) for path in
			(os.path.abspath(options.add),)][0]
	try:
		sys.path.insert(0, appdir)
		app = __import__(appname, globals(), locals(), [], -1)

		p = Plugin(uuid=app.UUID, name=appname, active=True, path=appdir)
		p.save()
		print " . App «%s» added. Please restart mother daemon" % p.name.encode('utf8')
	except Exception, e:
		print e; sys.exit(1)

	sys.exit(0)

if options.remove is not None:
	from mother.pluggable import Plugin
	from tentacles.queryset import filter

	name = options.remove
	#TODO: tentacles bug:  parenthesis priority is not translated into SQL
	for p in filter(lambda p: p.active == True and (p.name == name or p.uuid == name), Plugin):
		p.active = False; p.save()
		print " . App «%s» deactivated. Please restart mother daemon" % p.name.encode('utf8')
	sys.exit(0)


#NOTE: we can't use autoreload with twistd. see http://twistedmatrix.com/trac/ticket/4072
if __name__ == '__main__' and cfg.autoreload:
	autoreload.main(mom.run, kwargs={'foreground': foreground})
else:
	application = mom.run(foreground)
	

