from parallels.core.logging import get_logger
from parallels.core.actions.base.common_action import CommonAction
from parallels.core.converter.business_objects.common import SOURCE_TARGET
from parallels.plesk import messages
from parallels.plesk.utils.xml_rpc.plesk.operator.reseller_plan import \
    ResellerPlanOperator, ResellerPlanLimit, ResellerPlanPermission, ResellerPlanLimits, ResellerPlanApsPackage

logger = get_logger(__name__)


class DeployResellerPlans(CommonAction):
    def get_description(self):
        return messages.ACTION_CREATE_RESELLER_PLANS

    def get_failure_message(self, global_context):
        return messages.ACTION_CREATE_RESELLER_PLANS_FAILED

    def filter_action(self, global_context):
        plesk_server = global_context.conn.target.plesk_server
        return not plesk_server.is_power_user_mode and plesk_server.can_manage_resellers

    def run(self, global_context):
        """Create reseller plans in target Plesk

        :type global_context: parallels.core.global_context.GlobalMigrationContext
        """
        for plan in global_context.target_model.reseller_plans.values():
            self._create_plan(global_context, plan)

    def _create_plan(self, context, plan):
        """Create admin's reseller plan on target server

        :type context: parallels.core.global_context.GlobalMigrationContext
        :type plan: parallels.core.target_data_model.ResellerPlan
        """
        plan_name = plan.name.strip()
        if plan.source == SOURCE_TARGET:
            logger.debug(messages.ACTION_CREATE_RESELLER_PLANS_PLAN_EXISTS.format(
                reseller_plan_name=plan_name
            ))
            return
        with context.safe.try_plan(None, plan_name, messages.ACTION_CREATE_RESELLER_PLANS_PLAN_FAILED.format(
            reseller_plan_name=plan_name
        )):
            plesk_api = context.conn.target.plesk_api()
            plesk_api.send(
                ResellerPlanOperator.Add(
                    name=plan_name,
                    limits=ResellerPlanLimits(
                        overuse=plan.overuse,
                        oversell=plan.oversell,
                        limits=[ResellerPlanLimit(name, value) for name, value in plan.limits.items()]
                    ),
                    permissions=[ResellerPlanPermission(name, value) for name, value in plan.permissions.items()]
                )
            ).check()
            self._create_aps_bundle_filter(context, plan)

    @staticmethod
    def _create_aps_bundle_filter(context, plan):
        """
        :type context: parallels.core.global_context.GlobalMigrationContext
        :type plan: parallels.core.target_data_model.ResellerPlan
        """
        if plan.aps_bundle_filter is None:
            return
        if plan.aps_bundle_filter.type != 'white':
            # other types of APS filters are not supported
            return

        plesk_api = context.conn.target.plesk_api()

        api_filter = ResellerPlanOperator.FilterByName([plan.name.strip()])
        enable_aps_filter_request = ResellerPlanOperator.EnableApsFilter(filter=api_filter)
        plesk_api.send(enable_aps_filter_request).check()
        if len(plan.aps_bundle_filter.items) > 0:
            add_package_request = ResellerPlanOperator.AddPackage(
                filter=api_filter,
                packages=[
                    ResellerPlanApsPackage(name=package.name, value=package.value)
                    for package in plan.aps_bundle_filter.items
                ]
            )
            plesk_api.send(add_package_request).check()
