from parallels.core.actions.base.compound_action import CompoundAction
from parallels.core.actions.base.entry_point_action import EntryPointAction
from parallels.core.actions.base.legacy_action import LegacyAction
from parallels.core.actions.content.web.copy_windows_content_base import CopyWindowsWebContent
from parallels.core.actions.content.web.fix_unix_vhost_permissions \
    import FixUnixVhostPermissions
from parallels.core.actions.dns.forwarding.check_target_panel_supports_forwarding \
    import CheckTargetPanelSupportsForwarding
from parallels.core.actions.hosting_settings.remove_imported_backups import RemoveImportedBackups
from parallels.core.workflow.extension import WorkflowExtensionBase
from parallels.plesk.actions.check_versions import CheckVersions
from parallels.plesk.actions.hosting_settings.check.check_capability import CheckCapabilityAction
from parallels.plesk.source.plesk import messages
from parallels.plesk.source.plesk.actions.aps.import_backups_for_aps_restoration import ImportBackupsForApsRestore
from parallels.plesk.source.plesk.actions.aps.restore_applications \
    import RestoreApplications as ActionApsRestoreApplications
from parallels.plesk.source.plesk.actions.aps.transfer_packages \
    import TransferPackages as ActionApsTransferPackages
from parallels.plesk.source.plesk.actions.check.check_remote_smarter_mail import CheckSourceRemoteSmarterMailAction
from parallels.plesk.source.plesk.actions.check.check_source_account import CheckSourceAccountAction
from parallels.plesk.source.plesk.actions.check.check_transfer_error_docs import CheckTransferErrorDocsAction
from parallels.plesk.source.plesk.actions.check.extensions import CheckExtensionsAction
from parallels.plesk.source.plesk.actions.check_components import CheckComponents
from parallels.plesk.source.plesk.actions.content.mail.migrate_courier_to_dovecot import MigrateCourierToDovecot
from parallels.plesk.source.plesk.actions.content.web.copy_unix_content import CopyUnixWebContent
from parallels.plesk.source.plesk.actions.content.web.create_secured_web_content import CreateSecuredWebContent
from parallels.plesk.source.plesk.actions.content.web.fix_odbc_dsn_connection_status import FixOdbcDsnConnectionStatus
from parallels.plesk.source.plesk.actions.content.web.fix_permissions_for_iis6_domains \
    import FixPermissionsForIIS6Domains
from parallels.plesk.source.plesk.actions.content.web.transfer_security_files \
    import TransferSecurityFiles
from parallels.plesk.source.plesk.actions.content.web.fix_unix_permissions \
    import FixUnixPermissions
from parallels.plesk.source.plesk.actions.content.web.fix_unix_permissions_old_plesk \
    import FixUnixPermissionsOldPlesks
from parallels.plesk.source.plesk.actions.content.web.fix_unix_vhost_structure \
    import FixUnixVhostStructure
from parallels.plesk.source.plesk.actions.content.web.reset_permissions \
    import ResetPermissions
from parallels.plesk.source.plesk.actions.deploy.extensions.customers import DeployExtensionsCustomers
from parallels.plesk.source.plesk.actions.deploy.extensions.domains import DeployExtensionsDomains
from parallels.plesk.source.plesk.actions.deploy.extensions.resellers import DeployExtensionsResellers
from parallels.plesk.source.plesk.actions.deploy.extensions.server import DeployExtensionsServer
from parallels.plesk.source.plesk.actions.deploy.extensions.subdomains import DeployExtensionsSubdomains
from parallels.plesk.source.plesk.actions.deploy.extensions.subscription import DeployExtensionsSubscription
from parallels.plesk.source.plesk.actions.dns.forwarding.add_source_dns_acl import AddSourceToTargetDNSACL
from parallels.plesk.source.plesk.actions.dns.forwarding.add_source_dns_axfr import AddSourceToTargetDNSAXFR
from parallels.plesk.source.plesk.actions.fetch.decrypt_data import DecryptData
from parallels.plesk.source.plesk.actions.fetch.fetch_applications \
    import FetchApplicationsAction
from parallels.plesk.source.plesk.actions.fetch.fetch_backup import FetchBackupAction
from parallels.plesk.source.plesk.actions.fetch.fetch_capability_info import FetchCapabilityInfoAction
from parallels.plesk.source.plesk.actions.fetch.fetch_shallow_backup import FetchShallowBackupAction
from parallels.plesk.source.plesk.actions.fetch.merge_applications \
    import MergeApplications as FetchMergeApplicationsAction
from parallels.plesk.source.plesk.actions.hosting_settings.restore_additional_web_server_directives import \
    RestoreAdditionalWebServerDirectives
from parallels.plesk.source.plesk.actions.hosting_settings.transfer_error_documents \
    import TransferErrorDocuments
from parallels.plesk.source.plesk.actions.hosting_settings.transfer_mime_types \
    import TransferMIMETypes
from parallels.plesk.source.plesk.actions.hosting_settings.transfer_virtual_directories \
    import TransferVirtualDirectories
from parallels.plesk.source.plesk.actions.transfer_tomcat_applications import TransferTomcatApplications
from parallels.plesk.source.plesk.actions.wpb.transfer \
    import Transfer as TransferWPBSites


class WorkflowExtension(WorkflowExtensionBase):
    def extend_workflow(self, workflow):
        """Extend shared hosting workflow with source-panel specific actions

        :type workflow: parallels.core.workflow.base_workflow.BaseWorkflow
        """
        # check what interaction with source servers is going on via privileged system account, it should be done
        # before any operations with source servers to ensure what it has enough permissions
        workflow.get_shared_action('initial-pre-checks').insert_action(
            'check-source-account', CheckSourceAccountAction(), before='check-connections'
        )

        workflow.get_shared_action('initial-pre-checks').insert_action(
            'check-versions', CheckVersions(), after='check-connections'
        )
        workflow.get_shared_action('initial-pre-checks').insert_action(
            'check-components', CheckComponents(), after='check-versions'
        )

        workflow.get_path('transfer-accounts/deploy').insert_first_action(
            'deploy-extensions-server', DeployExtensionsServer()
        )
        workflow.get_path('transfer-accounts/deploy').insert_action(
            'deploy-extensions-resellers',
            DeployExtensionsResellers(),
            after='deploy-resellers'
        )
        workflow.get_path('transfer-accounts/deploy').insert_action(
            'deploy-extensions-customers',
            DeployExtensionsCustomers(),
            # Actually we want to insert action somewhere after customer is deployed.
            # As 'deploy-customers' action is removed from 'transfer-accounts/deploy' for Plesk Multi Server target,
            # and inserted much earlier in workflow outside of 'deploy',
            # we can't just write "after='deploy-customers'" here.
            # So we insert before action that is always after deploy customers action.
            before='deploy-panel-user-roles'
        )

        workflow.get_entry_point('transfer-accounts').insert_action(
            'copy-security', CompoundAction(), before='copy-content'
        )
        workflow.get_path('transfer-accounts/copy-security').insert_action(
            'transfer-security-files', TransferSecurityFiles()
        )
        workflow.get_path('transfer-accounts/copy-security').insert_action(
            'create-secured-web-content', CreateSecuredWebContent()
        )
        workflow.get_path('transfer-accounts/copy-security').insert_action(
            'reset-permissions', ResetPermissions()
        )
        workflow.get_path('transfer-accounts/copy-security').insert_action(
            'fix-permissions-for-iis6-domains', FixPermissionsForIIS6Domains()
        )

        workflow.get_shared_action('copy-web-files').insert_action(
            'copy-files-linux', CopyUnixWebContent()
        )
        workflow.get_shared_action('copy-web-files').insert_action(
            'copy-files-windows', CopyWindowsWebContent()
        )

        workflow.get_shared_action('copy-mail-content').insert_action(
            'migrate-courier-to-dovecot', MigrateCourierToDovecot()
        )

        workflow.get_shared_action('sync-web-content-assets').insert_action(
            'fix-unix-vhost-permissions', FixUnixVhostPermissions()
        )
        workflow.get_shared_action('sync-web-content-assets').insert_action(
            'fix-unix-vhost-structure', FixUnixVhostStructure()
        )
        workflow.get_shared_action('sync-web-content-assets').insert_action(
            'fix-permissions-old-plesks', FixUnixPermissionsOldPlesks()
        )
        workflow.get_shared_action('sync-web-content-assets').insert_action(
            'fix-permissions', FixUnixPermissions()
        )
        workflow.get_shared_action('sync-web-content-assets').insert_action(
            'transfer-tomcat-applications', TransferTomcatApplications()
        )
        workflow.get_shared_action('sync-web-content-assets').insert_action(
            'transfer-wpb-sites', TransferWPBSites()
        )
        workflow.get_shared_action('sync-web-content-assets').insert_action(
            'transfer-virtual-directories', TransferVirtualDirectories()
        )
        workflow.get_shared_action('sync-web-content-assets').insert_action(
            'transfer-error-documents', TransferErrorDocuments()
        )
        workflow.get_shared_action('sync-web-content-assets').insert_action(
            'transfer-mime-types', TransferMIMETypes()
        )
        workflow.get_shared_action('sync-web-content-assets').insert_action(
            'fix-odbc-dsn-connection-status', FixOdbcDsnConnectionStatus()
        )

        workflow.get_path('transfer-accounts').insert_action(
            'restore-aps', ActionApsRestoreApplications(),
            after='copy-content'
        )

        # deploy extensions data for subscriptions after all another hosting settings was already deployed
        workflow.get_path('transfer-accounts').insert_action(
            'deploy-extensions-per-subscription', CompoundAction(),
            after='restore-aps'
        )
        workflow.get_path('transfer-accounts/deploy-extensions-per-subscription').insert_action(
            'subscription', DeployExtensionsSubscription()
        )
        workflow.get_path('transfer-accounts/deploy-extensions-per-subscription').insert_action(
            'domains', DeployExtensionsDomains()
        )
        workflow.get_path('transfer-accounts/deploy-extensions-per-subscription').insert_action(
            'subdomains', DeployExtensionsSubdomains()
        )

        workflow.get_shared_action('fetch-source').insert_action(
            'fetch-configuration', FetchBackupAction()
        )
        workflow.get_shared_action('fetch-source').insert_action(
            'decrypt-data', DecryptData()
        )
        workflow.get_shared_action('fetch-source').insert_action(
            'fetch-applications', FetchApplicationsAction()
        )
        workflow.get_shared_action('fetch-source').insert_action(
            'merge-applications', FetchMergeApplicationsAction()
        )
        workflow.replace_shared_action('fetch-source-shallow', CompoundAction())
        workflow.get_shared_action('fetch-source-shallow').insert_action(
            'fetch-shallow-backup', FetchShallowBackupAction()
        )

        workflow.get_path('transfer-accounts/restore-hosting').insert_action(
            'restore-additional-directives', RestoreAdditionalWebServerDirectives(),
        )
        workflow.get_path('transfer-accounts').insert_action(
            'transfer-aps-packages', ActionApsTransferPackages(),
            after='windows-refresh-components'
        )

        # Import backups for APS applications restoration when running
        # 'copy-content' and 'copy-web-content' as separate actions
        workflow.get_path('copy-content').insert_action(
            'import-backups', ImportBackupsForApsRestore(),
            before='copy-content'
        )
        workflow.get_path('copy-content').insert_action(
            'remove-imported-backups', RemoveImportedBackups(),
            after='print-subscription-report'
        )
        workflow.get_path('copy-web-content').insert_action(
            'import-backups', ImportBackupsForApsRestore(),
            before='copy-web-content'
        )
        workflow.get_path('copy-web-content').insert_action(
            'remove-imported-backups', RemoveImportedBackups(),
            after='print-subscription-report'
        )

        workflow.replace_entry_point('set-dns-forwarding', EntryPointAction())
        workflow.replace_entry_point('undo-dns-forwarding', EntryPointAction())

        workflow.get_path('set-dns-forwarding').insert_action(
            'check-target-panel-supports-forwarding', CheckTargetPanelSupportsForwarding()
        )
        workflow.get_path('set-dns-forwarding').insert_actions(
            workflow.get_shared_action('prepare-assets').get_all_actions()
        )
        workflow.get_path('set-dns-forwarding').insert_action(
            'forward-dns', LegacyAction(
                description=messages.ACTION_FORWARD_DNS,
                function=lambda ctx: ctx.migrator._forward_dns(ctx.dns_forwarding_report_writer)
            )
        )
        workflow.get_path('set-dns-forwarding').insert_action(
            'cleanup',
            workflow.get_shared_action('cleanup')
        )
        workflow.get_path('set-dns-forwarding').insert_action(
            'print-report', LegacyAction(
                description=messages.ACTION_PRINT_FORWARDING_REPORT,
                function=lambda ctx: ctx.migrator._print_dns_forwarding_report(ctx.dns_forwarding_report)
            )
        )
        workflow.get_path('set-dns-forwarding').register_overall_shutdown('cleanup')

        workflow.get_path('undo-dns-forwarding').insert_action(
            'check-target-panel-supports-forwarding', CheckTargetPanelSupportsForwarding()
        )
        workflow.get_path('undo-dns-forwarding').insert_actions(
            workflow.get_shared_action('prepare-assets').get_all_actions()
        )
        workflow.get_path('undo-dns-forwarding').insert_action(
            'forward-dns', LegacyAction(
                description=messages.ACTION_UNDO_DNS_FORWARDING,
                function=lambda ctx: ctx.migrator._undo_dns_forwarding(ctx.dns_forwarding_report_writer)
            )
        )
        workflow.get_path('undo-dns-forwarding').insert_action(
            'cleanup',
            workflow.get_shared_action('cleanup')
        )
        workflow.get_path('undo-dns-forwarding').insert_action(
            'print-report', LegacyAction(
                description=messages.ACTION_PRINT_FORWARDING_REPORT,
                function=lambda ctx: ctx.migrator._print_dns_forwarding_report(ctx.dns_forwarding_report)
            )
        )
        workflow.get_path('undo-dns-forwarding').register_overall_shutdown('cleanup')

        # Set up low DNS timings
        workflow.replace_entry_point('set-low-dns-timings', EntryPointAction())
        workflow.get_path('set-low-dns-timings').insert_action(
            'set-low-dns-timings', LegacyAction(
                description=messages.ACTION_SET_LOW_DNS_TIMINGS,
                function=lambda ctx: ctx.migrator.set_low_dns_timings(ctx.options)
            )
        )

        # Transfer APS packages
        workflow.add_entry_point('transfer-aps-packages', EntryPointAction())
        workflow.get_path('transfer-aps-packages').insert_actions(
            workflow.get_shared_action('prepare-assets').get_all_actions()
        )
        workflow.get_path('transfer-aps-packages').insert_action(
            'transfer-aps-packages', ActionApsTransferPackages()
        )
        workflow.get_path('transfer-aps-packages').insert_action(
            'cleanup', workflow.get_shared_action('cleanup')
        )
        workflow.get_path('transfer-aps-packages').register_overall_shutdown('cleanup')

        # Restore APS applications
        workflow.add_entry_point('restore-aps-applications', EntryPointAction())
        workflow.get_path('restore-aps-applications').insert_actions(
            workflow.get_shared_action('prepare-assets').get_all_actions()
        )
        workflow.get_path('restore-aps-applications').insert_action(
            'import-backups', ImportBackupsForApsRestore()
        )
        workflow.get_path('restore-aps-applications').insert_action(
            'restore-applications', ActionApsRestoreApplications()
        )
        workflow.get_path('restore-aps-applications').insert_action(
            'cleanup', workflow.get_shared_action('cleanup')
        )
        workflow.get_path('restore-aps-applications').register_overall_shutdown('cleanup')

        # Capability checks
        workflow.get_shared_action('fetch-source').insert_action(
            'fetch-capability-info', FetchCapabilityInfoAction()
        )
        workflow.get_path('check/check-data').insert_action('check-capability', CheckCapabilityAction())
        workflow.get_shared_action('convert-hosting').insert_action('check-capability', CheckCapabilityAction())

        # Check ability to migrate extensions data
        workflow.get_path('check/check-data').insert_action('check-plesk-extensions', CheckExtensionsAction())

        # Check connections to source remote SmarterMail servers
        workflow.get_path('check').insert_action(
            'check-source-remote-smarter-mail', CheckSourceRemoteSmarterMailAction(),
            after='check-data'
        )

        # Check ability to transfer error docs
        workflow.get_path('check').insert_action(
            'check-transfer-error-docs', CheckTransferErrorDocsAction(),
            before='print-report'
        )

        # DNS forwarding
        workflow.get_path('set-dns-forwarding').insert_action(
            'add-source-to-target-dns-acl', AddSourceToTargetDNSACL(), before='forward-dns'
        )
        workflow.get_path('set-dns-forwarding').insert_action(
            'add-source-to-target-dns-axfr', AddSourceToTargetDNSAXFR(), before='forward-dns'
        )

        self._configure_entry_point_deploy_extensions(workflow)

    @staticmethod
    def _configure_entry_point_deploy_extensions(workflow):
        workflow.replace_entry_point('deploy-extensions', EntryPointAction())
        workflow.get_path('deploy-extensions').insert_action(
            'prepare-assets', workflow.get_shared_action('prepare-assets')
        )
        workflow.get_path('deploy-extensions').insert_action('deploy-extensions-server', DeployExtensionsServer())
        workflow.get_path('deploy-extensions').insert_action(
            'deploy-extensions-resellers', DeployExtensionsResellers()
        )
        workflow.get_path('deploy-extensions').insert_action(
            'deploy-extensions-customers', DeployExtensionsCustomers()
        )
        workflow.get_path('deploy-extensions').insert_action(
            'deploy-extensions-subscription', DeployExtensionsSubscription()
        )
        workflow.get_path('deploy-extensions').insert_action('deploy-extensions-domains', DeployExtensionsDomains())
        workflow.get_path('deploy-extensions').insert_action(
            'deploy-extensions-subdomains', DeployExtensionsSubdomains()
        )
        workflow.get_path('deploy-hosting-plans').insert_action(
            'cleanup', workflow.get_shared_action('cleanup')
        )
        workflow.get_path('deploy-hosting-plans').register_overall_shutdown('cleanup')
