from contextlib import contextmanager

import logging

from plesk_migrator.sdk.entity import Entity
from plesk_migrator.sdk.utils import safe_format, safe_string_repr, safe_idn_decode


class Context(Entity):
    """
    :type _reseller: str | unicode | None
    :type _customer: str | unicode | None
    :type _subscription: str | unicode | None
    :type _addon_domain: str | unicode | None
    :type _subdomain: str | unicode | None
    :type _alias: str | unicode | None
    :type _database: str | unicode | None
    :type _database_user: str | unicode | None
    :type _ftp_user: str | unicode | None
    :type _mailbox: str | unicode | None
    """
    def __init__(
            self, reseller=None, customer=None, subscription=None, addon_domain=None, subdomain=None, alias=None,
            database=None, database_user=None, ftp_user=None, mailbox=None
    ):
        self._reseller = reseller
        self._customer = customer
        self._subscription = subscription
        self._addon_domain = addon_domain
        self._subdomain = subdomain
        self._alias = alias
        self._database = database
        self._database_user = database_user
        self._ftp_user = ftp_user
        self._mailbox = mailbox

    @property
    def reseller(self):
        return self._reseller

    @property
    def customer(self):
        return self._customer

    @property
    def subscription(self):
        return self._subscription

    @property
    def addon_domain(self):
        return self._addon_domain

    @property
    def subdomain(self):
        return self._subdomain

    @property
    def alias(self):
        return self._alias

    @property
    def database(self):
        return self._database

    @property
    def database_user(self):
        return self._database_user

    @property
    def ftp_user(self):
        return self._ftp_user

    @property
    def mailbox(self):
        return self._mailbox


class Issue(object):
    """
    :type _details: str | unicode | None
    :type _message: str | unicode | None
    :type _context: Context
    """
    def __init__(self, details, message, context=None):
        self._details = details
        self._message = message
        self._context = context

    @property
    def details(self):
        return self._details

    @property
    def message(self):
        return self._message

    @property
    def context(self):
        return self._context


class Report(object):
    """
    :type _issues: [Issue]
    """
    def __init__(self):
        self._issues = []

    def add_issue(self, issue):
        """
        :type issue: Issue
        """
        self._issues.append(issue)

    def get_issues(self):
        """
        :rtype: [Issue]
        """
        return self._issues


dump_report = Report()


@contextmanager
def try_safe(error_message, context=None):
    """
    :type error_message: str | unicode
    :type context: Context
    """
    try:
        yield
    except Exception as e:
        logging.exception("Exception")
        dump_report.add_issue(Issue(
            details=unicode(e),
            message=error_message,
            context=context
        ))


def format_context(context):
    """
    :type context: Context
    :rtype: str | unicode | None
    """
    if context is None:
        return
    context_items = []
    if context.reseller:
        context_items.append(
            safe_format(u'Reseller "{reseller}"', reseller=context.reseller)
        )
    if context.customer:
        context_items.append(
            safe_format(u'Customer "{customer}"', customer=context.customer)
        )
    if context.subscription:
        context_items.append(
            safe_format(u'Subscription "{subscription}"', subscription=safe_idn_decode(context.subscription))
        )
    if context.addon_domain:
        context_items.append(
            safe_format(u'Addon domain "{addon_domain}"', addon_domain=safe_idn_decode(context.addon_domain))
        )
    if context.subdomain:
        context_items.append(
            safe_format(u'Subdomain "{subdomain}"', subdomain=safe_idn_decode(context.subdomain))
        )
    if context.alias:
        context_items.append(
            safe_format(u'Alias "{alias}"', alias=safe_idn_decode(context.alias))
        )
    if context.database:
        context_items.append(
            safe_format(u'Database "{database}"', database=context.database)
        )
    if context.database_user:
        context_items.append(
            safe_format(u'Database user "{database_user}"', database_user=context.database_user)
        )
    if context.ftp_user:
        context_items.append(
            safe_format(u'FTP user "{ftp_user}"', ftp_user=context.ftp_user)
        )
    if context.mailbox:
        context_items.append(
            safe_format(u'Mailbox "{mailbox}"', mailbox=context.mailbox)
        )
    if len(context_items) > 0:
        return u' - '.join(context_items)
    return u'Root elements'


def print_issues():
    print(u'MIGRATION STATUS:')
    for issue in dump_report.get_issues():
        print(safe_string_repr(format_context(issue.context)))
        print(u'    ' + safe_string_repr(issue.message))
        print(u'    Details:')
        print(u'        ' + safe_string_repr(issue.details))
    print(u'END OF MIGRATION STATUS')
