import posixpath
import string

from parallels.core.logging import get_logger
from parallels.core.runners.base import BaseRunner
from parallels.core.runners.entities import ExecutionOptions
from parallels.plesk.source.confixx import messages
from parallels.core import MigrationError
from parallels.core.utils.common import cached

logger = get_logger(__name__)


class ConfixxConfiguration(object):
    """Interface to Confixx panel server-wide settings.

    By default, main Confixx configuration file is located here:
    /root/confixx/confixx_main.conf
    """

    def __init__(self, confixx_server, config_path):
        self.confixx_server = confixx_server
        self.config_path = config_path
    
    def get_vhosts_dir(self):
        return self.get_config_var('user_homeDir', '/srv/www/htdocs')

    def get_client_id(self, domain_name): 
        return domain_name.split('.', 1)[0]

    def get_domain_vhost_dir(self, domain_name): 
        """Return filesystem path to domain hosting content directory.
        
        Directory names are extracted from system domain names. For example:
            'web1.confixx.test' -> 'web1'
        """
        directory_name = self.get_client_id(domain_name)
        vhosts_dir = self.get_config_var('user_homeDir', '/srv/www/htdocs')
        vhost_dir = posixpath.join(vhosts_dir, directory_name)
        logger.debug(messages.DEBUG_UNIX_VHOST_DIR, vhost_dir)
        return vhost_dir

    def get_mysql_user(self):
        return self.get_config_var('mysqlUserUser')

    def get_mysql_password(self):
        return self.get_config_var('mysqlUserPw')

    @cached
    def get_config_var(self, variable_name, default_value=None):
        with self.confixx_server.runner() as runner:
            assert isinstance(runner, BaseRunner)
            execution_results = runner.execute_command(
                "perl -e {perl_command}", dict(
                    perl_command='do "%s"; print $%s' % (self.config_path, variable_name)
                ),
                ExecutionOptions(ignore_exit_code=True)
            )
        value = execution_results.stdout.strip()
        if execution_results.exit_code == 0 and value != '':
            return value
        else:
            # in case of any error or empty value - fallback to default 
            logger.debug(
                messages.FAILED_TO_FIND_PARAMETER_IN_CONFIXX_CONFIG, variable_name, self.config_path
            )
            return default_value

    def is_maildir_used(self):
        """Return True, if Confixx uses maildir format."""
        return self.get_config_var('maildrop') == 'HOMEDIR/Maildir/'

    def get_mailbox_root(self):
        """Return the directory, where mail content is stored."""
        maildrop = self.get_config_var('maildrop', '/var/spool/mail/USER')
        maildrop = string.rstrip(maildrop, '/ ')
        if maildrop == '/var/spool/mail/USER':
            return '/var/spool/mail'
        elif maildrop == 'HOMEDIR/Maildir' or maildrop == 'HOMEDIR/Mailbox':
            return self.get_config_var('pop_homeDir', '/home/email')
        else:
            raise MigrationError(
                messages.CANNOT_DETECT_CONFIXX_MAIL_STORAGE_DIR % maildrop
            )

    def get_mailbox_path(self, mailusername):
        """Return path to user's mailbox."""
        mail_root_dir = self.get_mailbox_root() 
        maildrop = self.get_config_var('maildrop', '/var/spool/mail/USER')
        if maildrop == '/var/spool/mail/USER':
            path = (mail_root_dir, mailusername)
        elif maildrop == 'HOMEDIR/Mailbox':
            path = (mail_root_dir, mailusername, 'Mailbox') 
        else:
            raise MigrationError(
                messages.CANNOT_DETERMINE_MAILBOX_LOCATION %
                mailusername
            )
        return posixpath.join(*path)
