#!/usr/bin/python3
#
# Store users in imapauth table.
# User defaults from database or defaults from config file
#
# -*- coding: utf-8 -*-
#
# Benno MailArchiv
#
# Copyright 2018-2021 LWsystems GmbH
#
# http://www.lw-systems.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 argparse
import sys
import os
import logging

from Benno.IMAP.Config import Config
from Benno.IMAP.User import UserError, IMAPUser
from Benno.RSAkey import RSAkey

versionstring='benno-imapuser 3.0.0'


def print_userdata(user):
    print("Id:        %s" % user.id)
    print("Userid:    %s" % user.imapuser)
    print("Imaphost   %s" % user.imaphost)
    print("Name:      %s" % user.name)
    print("Container: ", end="")
    for cnt in user.archive:
        print("%s " % cnt, end="")
    print()
    print("E-Mail:    ", end="")
    for addr in user.email:
        print("%s " % addr, end="")
    print()
    print("Status:    %s" % user.status)
    if args.imapstatus:
        print("IMAP next:", end = '')
        for folder in user.imapstatus.getFolderlist():
            print(" %s#%s" % (folder,user.imapstatus.getFolderstatus(folder)))
    print("")

### MAIN #################
if __name__ == "__main__":
    configfile=os.getenv('CONFIGFILE','/etc/benno-imap/imapauth.conf')
    parser = argparse.ArgumentParser(description='Create and edit Benno IMAP users')
    parser.add_argument('-v', '--version', action='store_true')
    parser.add_argument('-l', '--list', action='store_true', help='List all users')
    parser.add_argument('-r', '--reset', action='store_true', help='Reset IMAP folder status')
    parser.add_argument('-D', '--delete', action='store_true')
    parser.add_argument('-c', '--config', help='config file (/etc/benno-imap/imapauth.conf)', default='%s' % configfile)
    parser.add_argument('-u', '--user', help='username (Shows user data if no other option)')
    parser.add_argument('-i', '--imaphost', help='IMAP hostname')
    parser.add_argument('-p', '--password', help='Store IMAP password')
    parser.add_argument('-e', '--email', help='Email adress(es) [-e addr1,addr2,..,addrn]', nargs='?', const='')
    parser.add_argument('-C', '--container', help='Container(s) [-C C1,C2,..,Cn]', nargs='?', const='')
    parser.add_argument('-n', '--name', help='Display name of the user')
    parser.add_argument('-S', '--status', help='Status of the user (0: disabled, 1: import, 2: login, 3:import+login')
    parser.add_argument('-I', '--imapstatus', action='store_true', help='IMAP folder status')
    parser.add_argument('-L', '--loglevel', default='ERROR', help='loglevel (default=ERROR, values: CRITICAL, ERROR, WARNING, INFO, DEBUG')
    args = parser.parse_args()

    imapuser=''
    password=''
    name=''
    imaphost=''
    email=''
    container=''
    listuser=False
    deleteuser=False
    deletearchive=False
    deleteemail=False
    reset=False
    status=''

    if args.version:
        print(versionstring)
        sys.exit()

    try:
        config = Config(args.config)
    except (FileNotFoundError, PermissionError):
        print('Cannot read configfile %s' % args.config)
        parser.print_usage()
        sys.exit(1)
    config.add_section('LOG')
    config.set('LOG','loglevel',args.loglevel.upper())
    config.set('DEFAULT','archive','BennoContainer')

    logger=logging.getLogger(__name__)
    logger.setLevel(config.get('LOG','loglevel'))
    ch=logging.StreamHandler()
    formatter = logging.Formatter('%(levelname)s: %(message)s')
    ch.setFormatter((formatter))
    logger.addHandler(ch)

    logger.info("Read file \"%s\"", args.config)

    if args.list:
        for iuser in IMAPUser.List(config):
            print("# -u %s -i %s" % (iuser.imapuser, iuser.imaphost))
        sys.exit(0)
    if not args.imaphost:
        imaphost=config.get('DEFAULT','host')
    if not args.user:
        parser.print_usage()
        sys.exit(1)
    try:
        user = IMAPUser.CreateImapData(config, args.user, args.imaphost)
    except UserError as e:  # user not in db
        user = IMAPUser(config, args.user, args.imaphost)
    except Exception as e:
        logger.debug(e)
        print('User "%s@%s" does not exist.' % (args.user, args.imaphost))
        sys.exit(1)
    if args.delete:
        IMAPUser.Delete(user)
        print('User %s deleted.' % user.id)
        sys.exit(0)
    changeuser=False
    if args.password:
        keyfile = config.get(user.id, 'keyfile')
        key = open(keyfile).read()
        user.imappassword = RSAkey.encrypt(key, args.password)
        changeuser=True
    if args.name:
        user.name=args.name
        changeuser=True
    if args.status:
        user.status=args.status
        changeuser=True
    if args.email:
        user.email=''.join(args.email.split()).split(',')           # remove whitespace and convert to list
        changeuser=True
    if args.container:
        user.archive=''.join(args.container.split()).split(',')      # remove whitespace and convert to list
        changeuser=True
    if args.reset:
        user.resetMailbox()
        changeuser=True
    try:
        if args.container=='':   #delete contents
            default_container = config.get(user.id,'archive')
            user.archive=[default_container]
            changeuser=True
        if args.email=='':
            user.email=[]
            changeuser=True
    except UserError as e:
        if not changeuser:
            sys.exit(e.msg)
    if changeuser:
        # store user
        try:
            user.save()
            print("User changed:")
            print_userdata(user)
        except Exception as e:
            logger.error("Cannot store user: %s", e)
        sys.exit(1)
    else:
        print_userdata(user)

