#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
#
# Univention zimbra4ucs connector
#
# Copyright 2017 Univention GmbH
#
# http://www.univention.de/
#
# All rights reserved.
#
# The source code of this program is made available
# under the terms of the GNU Affero General Public License version 3
# (GNU AGPL V3) as published by the Free Software Foundation.
#
# Binary versions of this program provided by Univention to you as
# well as other copyrighted, protected or trademarked materials like
# Logos, graphics, fonts, specific documentations and configurations,
# cryptographic keys etc. are subject to a license agreement between
# you and Univention and not subject to the GNU AGPL V3.
#
# In the case you use this program under the terms of the GNU AGPL V3,
# the program is provided 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License with the Debian GNU/Linux or Univention distribution in file
# /usr/share/common-licenses/AGPL-3; if not, see
# <http://www.gnu.org/licenses/>.

import logging
import time
import os
import optparse
import sys
import daemon.runner

import zimbra4ucs.tools
import univention.config_registry

ucr = univention.config_registry.ConfigRegistry()
ucr.load()


class App(object):

	def __init__(self, opts):
		self.opts = opts
		self.pidfile_timeout = 5
		self.pidfile_path = '/var/run/zimbra4ucs.pid'
		if self.opts.dry_run:
			self.stdin_path = '/dev/stdin'
			self.stdout_path = '/dev/stdout'
			self.stderr_path = '/dev/stderr'
		else:
			self.stdin_path = os.path.devnull
			self.stdout_path = os.path.devnull
			self.stderr_path = os.path.devnull

	def run(self):
		while True:
			try:
				logger.info('checking changes for maildomains')
				zimbra4ucs.tools.ImportDomain.process_files(
					self.opts.data_dir_maildomain,
					opts.dry_run)
				logger.info('checking changes for user')
				zimbra4ucs.tools.ImportUser.process_files(
					self.opts.data_dir_user,
					opts.dry_run)
			except Exception:
				ex_type, ex, tb = sys.exc_info()
				logger.exception(tb)
			if self.opts.dry_run:
				logger.info('dry run, good bye')
				return
			else:
				time.sleep(5)


# options
usage = 'usage: %prog start|stop|restart [options]'
parser = optparse.OptionParser(usage=usage)
parser.add_option(
	'-n', '--dry-run', dest='dry_run',
	default=False, action='store_true',
	help='test run, don\'t create, don\'t remove')
parser.add_option(
	'-d', '--data-dir-user', dest='data_dir_user',
	default=ucr.get('zimbra4ucs/user/listener/dir', '/var/lib/zimbra4ucs-user-listener'),
	help='a directory with pickle files to process')
parser.add_option(
	'-m', '--data-dir-maildomain', dest='data_dir_maildomain',
	default=ucr.get('zimbra4ucs/maildomain/listener/dir', '/var/lib/zimbra4ucs-maildomain-listener'),
	help='a directory with pickle files to process')
parser.add_option(
	'-l', '--log-file', dest='log_file',
	default=ucr.get('zimbra4ucs/connector/logfile', '/var/log/univention/zimbra4ucs.log'),
	help='log file')
parser.add_option(
	'-v', '--log-level', dest='log_level',
	default=ucr.get('zimbra4ucs/connector/loglevel', '3'),
	help='log level')
opts, args = parser.parse_args()

# logging
if opts.log_level == '1':
	level = logging.ERROR
elif opts.log_level == '2':
	level = logging.WARN
elif opts.log_level == '3':
	level = logging.INFO
elif opts.log_level == '4':
	level = logging.DEBUG
else:
	raise ValueError('--log-level must be one of 1, 2, 3 or 4!')
logger = logging.getLogger('zimbra4ucs')
formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
if opts.log_file == '-':
	handler = logging.StreamHandler()
else:
	handler = logging.FileHandler(opts.log_file)
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(level)
if 'start' in args:
	logger.info('started with args: %s, opts: %s' % (args, opts))

# run one shot or as daemon
daemon_mode = not opts.dry_run
app = App(opts=opts)
daemon_runner = daemon.runner.DaemonRunner(app)
daemon_runner.daemon_context.files_preserve = [handler.stream]
daemon_runner.daemon_context.detach_process = daemon_mode
daemon_runner.do_action()

sys.exit(0)
