import os
import ntpath

import parallels.plesk.source.plesk
from parallels.core.logging import get_logger
from parallels.core.runners.base import BaseRunner
from parallels.plesk.source.plesk import messages
from parallels.core.utils.common import between_inclusive
from parallels.core.actions.base.common_action import CommonAction
from parallels.core.actions.utils.logging_properties \
    import LoggingProperties
from parallels.core.utils import migrator_utils
from parallels.core.utils.yaml_utils import write_yaml


logger = get_logger(__name__)


class FetchApplicationsAction(CommonAction):
    def get_description(self):
        return messages.ACTION_FETCH_APPLICATIONS_DESCRIPTION

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

    def get_logging_properties(self):
        return LoggingProperties(compound=False)

    def is_critical(self):
        """If action is critical or not

        If action is critical and it failed, migration tool won't run the next operations.

        :rtype: bool
        """
        return False

    def run(self, global_context):
        """
        :type global_context: parallels.plesk.source.plesk.global_context.PleskGlobalMigrationContext
        """
        for source_id in global_context.conn.get_source_plesks():
            logger.debug(messages.FETCH_INFORMATION_ABOUT_WEB_APPLICATIONS_INSTALLED, source_id)

            source_server = global_context.conn.get_source_node(source_id)
            with source_server.runner() as runner_source:
                assert isinstance(runner_source, BaseRunner)

                use_external_applications_file = ( 
                    source_server.is_windows() and
                    between_inclusive(
                        source_server.plesk_version,
                        (10, 3), (11, 1)
                    )
                )

                if not use_external_applications_file:
                    continue

                applications_filename = global_context.session_files.get_path_to_applications_filename(source_id)
                
                if not global_context.options.reload_source_data and os.path.exists(applications_filename):
                    continue

                script_name = "WindowsApsBackup.phpe"
                remote_script_path = source_server.get_session_file_path(script_name)
                runner_source.upload_file(
                    migrator_utils.get_package_extras_file_path(
                        parallels.plesk.source.plesk, script_name
                    ), 
                    remote_script_path
                )
                applications = runner_source.execute_command(
                    u'{php_bin} -dauto_prepend_file="" -d display_errors="On" {windows_aps_backup}',
                    dict(
                        php_bin=ntpath.join(source_server.plesk_dir, u'admin\\bin\\php.exe'),
                        windows_aps_backup=remote_script_path
                    )
                ).stdout.decode('utf-8')

                write_yaml(applications_filename, applications)
