from parallels.core.utils.common import cached
from parallels.plesk.utils.xml_rpc.plesk import operator as plesk_ops
from parallels.plesk.utils.xml_rpc.plesk.operator import ServicePlanOperator, ResellerPlanOperator


def get_subscription_sysuser_name(plesk_api, subscription_name):
    hosting = plesk_api.send(plesk_ops.SubscriptionOperator.Get(
        filter=plesk_ops.SubscriptionOperator.FilterByName([subscription_name]),
        dataset=[plesk_ops.SubscriptionOperator.Dataset.HOSTING]
    ))[0].data[1].hosting
    if isinstance(hosting, plesk_ops.SubscriptionHostingVirtual):
        return hosting.properties.get('ftp_login')
    else:
        return None


@cached
def get_service_template_allowed_hosting_settings(plesk_api):
    """Get set of allowed hosting settings for hosting service templates on specified Plesk

    :type plesk_api: parallels.plesk.utils.xml_rpc.plesk.client.Client
    :rtype: set[str | unicode]
    """
    request = ServicePlanOperator.GetPhysicalHostingDescriptor(
        filter=ServicePlanOperator.FilterAll()
    )
    result = plesk_api.send(request)
    return {prop.name for prop in result.data.properties}


@cached
def get_service_template_allowed_permissions(plesk_api):
    """Get set of allowed permissions for hosting service templates on specified Plesk

    :type plesk_api: parallels.plesk.utils.xml_rpc.plesk.client.Client
    :rtype: set[str | unicode]
    """
    request = ServicePlanOperator.GetPermissionDescriptor(
        filter=ServicePlanOperator.FilterAll()
    )
    result = plesk_api.send(request)
    return {name for name in result.data.properties}


@cached
def get_service_template_allowed_limits(plesk_api):
    """Get set of allowed limits for hosting service templates on specified Plesk

    :type plesk_api: parallels.plesk.utils.xml_rpc.plesk.client.Client
    :rtype: set[str | unicode]
    """
    request = ServicePlanOperator.GetLimitDescriptor(
        filter=ServicePlanOperator.FilterAll()
    )
    result = plesk_api.send(request)
    return {name for name in result.data.properties}


@cached
def get_reseller_template_allowed_permissions(plesk_api):
    """Get set of allowed permissions for hosting service templates on specified Plesk

    :type plesk_api: parallels.plesk.utils.xml_rpc.plesk.client.Client
    :rtype: set[str | unicode]
    """
    request = ResellerPlanOperator.GetPermissionDescriptor(
        filter=ResellerPlanOperator.FilterAll()
    )
    result = plesk_api.send(request)
    return {name for name in result.data.properties}


@cached
def get_reseller_template_allowed_limits(plesk_api):
    """Get set of allowed limits for hosting service templates on specified Plesk

    :type plesk_api: parallels.plesk.utils.xml_rpc.plesk.client.Client
    :rtype: set[str | unicode]
    """
    request = ResellerPlanOperator.GetLimitDescriptor(
        filter=ResellerPlanOperator.FilterAll()
    )
    result = plesk_api.send(request)
    return {name for name in result.data.properties}


def get_subscription_db_servers(plesk_api, subscription_name):
    request = plesk_ops.SubscriptionOperator.DbServers.List(
        plesk_ops.SubscriptionOperator.FilterByName([subscription_name])
    )
    return request_single_optional_item(plesk_api, request, default=[])


def request_single_optional_item(plesk_api, request, default=None):
    response = plesk_api.send(request)
    for result in response:
        if not hasattr(result, 'code') or result.code != 1013:
            return result.data

    return default
