"""
This module defines `Celery`_ tasks to manage file system entities.

.. _Celery: http://www.celeryproject.org/

"""
from __future__ import absolute_import, unicode_literals

import os
import subprocess

from django.conf import settings

from celery import shared_task
from celery.utils.log import get_task_logger

from gvafile.exceptions import GVAFileException


_logger = get_task_logger(__name__)

SUDO_CMD = '/usr/bin/sudo'
INSTALL_CMD = '/usr/bin/install'
SETFACL_CMD = '/usr/bin/setfacl'
RM_CMD = '/bin/rm'


def _build_sftp_directory_name(username):
    """
    Constructs the SFTP directory name for a given username.

    """
    return os.path.join(settings.GVAFILE_SFTP_DIRECTORY, username)


def _build_mail_directory_name(username):
    """
    Constructs the mailbox directory name for a given username.

    """
    return os.path.join(settings.GVAFILE_MAIL_DIRECTORY, username)


@shared_task
def setup_file_sftp_userdir(username):
    """
    This task creates the home directory for an SFTP user if it does not exist
    yet.

    :param str username: the user name
    :raises Exception: if the SFTP directory of the user cannot be created
    :return: the created directory name
    :rtype: str

    """
    sftp_directory = _build_sftp_directory_name(username)
    try:
        subprocess.check_output([
            SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username,
            '-m', '0750', '-d', sftp_directory], stderr=subprocess.STDOUT)
        subprocess.check_output([
            SUDO_CMD, SETFACL_CMD, '-m', 'www-data:--x',
            sftp_directory], stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError:
        _logger.exception(
            'could not create SFTP directory for user %s', username)
        raise GVAFileException(
            "could not create SFTP directory for user %s" % username)
    return sftp_directory


@shared_task
def delete_file_sftp_userdir(username):
    """
    This task recursively deletes the home directory of an SFTP user if it
    does not exist yet.

    :param str username: the user name
    :raises Exception: if the SFTP directory of the user cannot be removed
    :return: the removed directory name
    :rtype: str

    """
    sftp_directory = _build_sftp_directory_name(username)
    try:
        subprocess.check_output([
            SUDO_CMD, RM_CMD, '-r', '-f', sftp_directory],
            stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError:
        _logger.exception(
            'could not remove SFTP directory for user %s', username)
        raise GVAFileException(
            "could not remove SFTP directory for user %s" % username)
    return sftp_directory


@shared_task
def setup_file_mail_userdir(username):
    """
    This task creates the mail base directory for a user if it does not exist
    yet.

    :param str username: the user name
    :raises Exception: if the mail base directory for the user cannot be
        created
    :return: the created directory name
    :rtype: str

    """
    mail_directory = _build_mail_directory_name(username)
    try:
        subprocess.check_output([
            SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username,
            '-m', '0750', '-d', mail_directory], stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError:
        _logger.exception(
            'could not create mail base directory for user %s', username)
        raise GVAFileException(
            "could not create mail base directory for user %s" % username)
    return mail_directory


@shared_task
def delete_file_mail_userdir(username):
    """
    This task recursively deletes the mail base directory for a user if it
    does not exist yet.

    :param str username: the user name
    :raises Exception: if the mail base directory of the user cannot be removed
    :return: the removed directory name
    :rtype: str

    """
    mail_directory = _build_mail_directory_name(username)
    try:
        subprocess.check_output([
            SUDO_CMD, RM_CMD, '-r', '-f', mail_directory],
            stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError:
        _logger.exception(
            'could not remove mail base directory of user %s', username)
        raise GVAFileException(
            "could not remove mail base directory of user %s" % username)
    return mail_directory