#!/usr/bin/env python
# coding:utf-8

import ast
from cplLdaptool import LdapMod
from .plugin import PluginAbstract, ModList
from .mailwhitelist import WhileListUpload
from .roundcube import Roundcube, PostgresDB
from .imapmail import ImapMail


msg0001 = 'no orig mail addresses provided in command call'
msg0002 = 'unable to coerce sting of mail addresses to list: \'{0}\''
msg0003 = 'unable fo find a primary mail address for: \'{0}\''
msg0004 = 'no mail addresses to remove from forwarders for: \'{0}\''
msg0005 = 'removing mail forwarders for user: \'{0}\''
msg0006 = 'saved mail addresses string: {0}'
msg0007 = 'saved mail addresses: {0}'
msg0008 = 'current mail addresses: {0}'
msg0009 = 'removed mail addresses: {0}'
msg0010 = 'new mail addresses: {0}'
msg0011 = 'removing forwarders from \'{0}\''
msg0012 = 'forwarders in group: \'{0}\''
msg0013 = 'failed to remove mail forwarder(s) {0} from \'{1}\''
msg0014 = 'successfull removed mail forwarder(s) {0} from \'{1}\''
msg0015 = 'failed to add mail forwarder \'{0}\' to \'{1}\''
msg0016 = 'successfull added mail forwarder \'{0}\' to \'{1}\''
msg0017 = 'more than one forwarder for \'{0}\' in group \'{1}\' : {2}'
msg0018 = 'existing mail forwarder {0} in \'{1}\''

msg0100 = 'fetching configuration for: \'{0}\''


class GosaMailAccount(PluginAbstract, Roundcube, ImapMail, WhileListUpload, metaclass=ModList):

	def __init__(self, postcmd):

		super().__init__(postcmd)
		super(PluginAbstract, self).__init__(postcmd)
		super(Roundcube, self).__init__(postcmd)
		#super(ImapMail, self).__init__(postcmd)

		self.ldapmod = LdapMod(self.gosa_ldap, self.logger)


#	def __del__(self):

#		ImapMail.__del__(self)
#		SSHFS.__del__(self)


	def _getImapConfig(self, imap_name):

		imap_cfg_def = {
			'mailboxbase' : ('user', ),
			'mailboxsharebase' : ('Other Users', ),
			'proxyacl' : 'lrswipkxtecd',
			'mailarchivemode' : '',
			'mailarchive' : '',
			'appendtimestamp' : True,
			'deletemailbox' : False,
			'skipspecial' : True,
			'mountbase' : '/mnt/pygosa',
			'sshhost' : '',
			'sshuser' : 'root',
			'sshpwd' : '',
			'sshkey' : '',
			'sshport' : '',
			'sshhkeysave' : True,
			'sshhkeypol' : 'reject',
			}

		imap_cfg_ver = {
			'mailboxbase' : ('list', 'str', ),
			'mailboxsharebase' : ('list', 'str', ),
			'proxyacl' : ('str', ),
			'mailarchivemode' : ('str', ),
			'mailarchive' : ('list', 'str', ),
			'appendtimestamp' : ('bool', ),
			'deletemailbox' : ('bool', ),
			'skipspecial' : ('bool', ),
			'mountbase' : ('str', ),
			'sshhost' : ('str', ),
			'sshuser' : ('str', ),
			'sshpwd' : ('str', ),
			'sshkey' : ('str', ),
			'sshport' : ('int', ),
			'sshhkeysave' : ('bool', ),
			'sshhkeypol' : ('str', ),
			}

		# get imap configuration
		self.logger.debug(msg0100.format(self.class_name + '/' + imap_name))
		self.config.updateDefaults(self.class_name + '/' + imap_name, imap_cfg_def)
		self.config.updateVerify(imap_cfg_ver)

		return self.config.getSection(self.class_name + '/' + imap_name)


	def create(self):

		self.whitelistUpload()


	def modify(self):

		self.whitelistUpload()
		self.removeForwarders()

	
	def remove(self):

		pass


	def preremove(self):

		self.whitelistUpload()
		self.removeRoundcubeUser()
		self.removeForwarders(True)
		self.delMailbox()


	def removeForwarders(self, remove=False):

		mail_a = 'mail'
		amail_a = ('gosaMailAlternateAddress', )
		maa = ""
		ma = ""
		attr = ""
		fwd_a = "gosaMailForwardingAddress"
		oclasses = ('posixGroup', 'gosaMailAccount', )
		mail = ""
		amails = []
		fwds = []
		ufwds = []
		omails_str = ""
		omails = []
		cmails = []
		rmails = []
		rmails_re = []
		#nmails = []
		fmails = []
		fgroups = []
		fgroup = ""
		groupdn = ""
		searchf = ""
		mod_list = []

		self.logger.info(msg0005.format(self.cn))

		if not remove:
			# get saved mail addresses before possible change
			try:
				omails_str = self.opt[0]
				self.logger.debug(msg0006.format(omails_str))
				omails = ast.literal_eval(omails_str)
				self.logger.debug(msg0007.format(omails))

			except IndexError:
				self.logger.info(msg0001)
				return

			except SyntaxError:
				self.logger.error(msg0002.format(omails_str))
				return

		# get current mail addresses
		# main address
		try:
			mail = self.ldap_data[mail_a][0].decode()
			cmails.append(mail)

		except KeyError:
			self.logger.error(msg0003.format(self.cn))
			return

		# add additional mail attributes
		for maa in amail_a:
			try:
				amails.extend([ ma.decode() for ma in self.ldap_data[maa] ])
			except KeyError: pass

		if amails:
			cmails.extend(amails)

		self.logger.debug(msg0008.format(cmails))

		if remove:
			# add all current mail addresses to the list of addresses
			# to be removed in case of an account removal
			rmails = cmails
		else:
			# calculate removed mail addresses
			rmails = [ ma for ma in omails if ma not in set(cmails) ]
			self.logger.debug(msg0009.format(rmails))

			# calculate new mail addresses
			#nmails = [ ma for ma in cmails if ma not in set(omails) ]
			#self.logger.debug(msg0010.format(nmails))

		# return here if no mail addresses where removed
		if not rmails:
			self.logger.info(msg0004.format(self.cn))
			return

		# gather all forwarding groups in which removed mail
		# addresses occur
		searchf  = '(&'
		searchf += ''.join([ '(objectClass={0})'.format(attr) for attr in oclasses ])
		searchf += '(|'
		searchf += ''.join([ '({0}={1})'.format(fwd_a, ma) for ma in rmails ])
		searchf += '))'

		fgroups = self.gosa_ldap.searchLdap( self.searchbase,
			'sub', searchf, [fwd_a,] )

		# cycle though the found forwarding groups
		for fgroup in fgroups:

			groupdn = fgroup[0]
			self.logger.info(msg0011.format(groupdn))
			fwds = [ ma.decode() for ma in fgroup[1][fwd_a] ]
			self.logger.debug(msg0012.format(fwds))

			# delete forearders listed as removed
			rmails_re = [ '^{0}$'.format(ma) for ma in rmails ]

			mod_list = (
				(
					(groupdn, 'base', '(objectClass=*)', (fwd_a, ) ), (
						('attrib', 'delete', rmails_re, (fwd_a, ), ),
					)
				),
			)

			if not self.ldapmod.modify(mod_list):
				self.logger.error(msg0013.format(rmails, groupdn))
				continue

			self.logger.info(msg0014.format(rmails, groupdn))

			# continue here, if we remove the user account...
			if remove: continue

			# ... otherwise add main mail address to the forwarders
			# if there is none of the users current addresses in the
			# list anymore
			ufwds = [ ma for ma in cmails if ma in fwds ]

			if not ufwds:

				mod_list = (
					(
						(groupdn, 'base', '(objectClass=*)', (fwd_a, ) ), (
							('attrib', 'add', (mail, ), (fwd_a, ), ),
						)
					),
				)

				if not self.ldapmod.modify(mod_list):
					self.logger.error(msg0015.format(mail, groupdn))
					continue

				self.logger.info(msg0016.format(mail, groupdn))

			elif len(ufwds) > 1:

				# warn if the user has mutliple forward addresses
				# within the group
				self.logger.warn(msg0017.format(self.cn, groupdn, ufwds))
			else:
				self.logger.debug(msg0018.format(ufwds, groupdn))


