from parallels.core import messages
from parallels.core.actions.base.common_action import CommonAction
from parallels.core.existing_objects_model import ExistingObjectsModel
from parallels.core.logging import get_logger
from parallels.core.utils.yaml_utils import write_yaml

logger = get_logger(__name__)


class FetchTargetAction(CommonAction):
    def get_description(self):
        """Get short description of action as string

        :rtype: str | unicode
        """
        return messages.ACTION_FETCH_TARGET_INFO_DESCRIPTION

    def get_failure_message(self, global_context):
        """
        :type global_context: parallels.core.global_context.GlobalMigrationContext
        """
        return messages.ACTION_FETCH_TARGET_INFO_FAILURE

    def run(self, global_context):
        """
        :type global_context: parallels.core.global_context.GlobalMigrationContext
        """
        global_context.target_existing_objects = self._read_from_panel(
            global_context,
            global_context.migration_list_data.resellers.keys(),
            global_context.migration_list_data.customers_mapping.keys(),
            global_context.migration_list_data.subscriptions_mapping.keys(),
        )

        target_filename = global_context.session_files.get_path_to_existing_objects_model()
        write_yaml(target_filename, global_context.target_existing_objects)

    @staticmethod
    def _read_from_panel(
        global_context, reseller_logins, customer_logins, subscription_names
    ):
        """Fetch information about objects existing on target panel

        Fetch it only for the specified resellers, clients, subscriptions.

        :param list[str | unicode] reseller_logins: fetch resellers with these logins
        :param list[str | unicode] customer_logins: fetch customers with these logins
        :param list[str | unicode] subscription_names: fetch target subscriptions with these names
        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :rtype: parallels.core.existing_objects_model.ExistingObjectsModel
        """
        admin_id = global_context.hosting_repository.panel.get_administrator_id(None)

        logger.info(messages.GET_TARGET_PANEL_RESELLERS)
        resellers = {
            reseller.username: reseller
            for reseller in global_context.hosting_repository.reseller.get_list(
                filter_username=reseller_logins
            )
        }

        logger.info(messages.GET_TARGET_PANEL_PLANS)
        plans = []
        addon_plans = []
        for owner_id in [admin_id] + [reseller.reseller_id for reseller in resellers.values()]:
            plans += global_context.hosting_repository.service_plan.get_list(
                filter_owner_id=[owner_id]
            )
            addon_plans += global_context.hosting_repository.service_plan_addon.get_list(
                filter_owner_id=[owner_id]
            )

        logger.info(messages.GET_TARGET_PANEL_CUSTOMERS)
        customers = {
            customer.username: customer
            for customer in global_context.hosting_repository.customer.get_list(
                filter_username=customer_logins
            )
        }

        logger.info(messages.GET_TARGET_DOMAINS)
        subscriptions = global_context.hosting_repository.subscription.get_list(filter_name=subscription_names)
        domain_aliases = global_context.hosting_repository.domain_alias.get_list()
        subdomains = global_context.hosting_repository.subdomain.get_list()
        domains = global_context.hosting_repository.domain.get_list()

        return ExistingObjectsModel(
            resellers=resellers,
            customers=customers,
            plans=plans,
            addon_plans=addon_plans,
            subscriptions=subscriptions,
            domains=domains,
            domain_aliases=domain_aliases,
            subdomains=subdomains,
            ip_addresses=global_context.conn.target.plesk_server.get_all_ips()
        )
