from parallels.core.actions.base.compound_action import CompoundAction
from parallels.core.actions.base.entry_point_action import EntryPointAction
from parallels.core.workflow.base_workflow import BaseWorkflow
from parallels.core.workflow.builder import WorkflowBuilderBase
from parallels.core.workflow.extension import WorkflowExtensionBase
from parallels.plesk.source.web import messages
from parallels.plesk.source.web.actions.adjust.application_database_host import AdjustApplicationDatabaseHost
from parallels.plesk.source.web.actions.adjust.application_database_name import AdjustApplicationDatabaseName
from parallels.plesk.source.web.actions.adjust.application_database_user import AdjustApplicationDatabaseUser
from parallels.plesk.source.web.actions.adjust.base_url_change_in_db import AdjustBaseUrlChangeInDB
from parallels.plesk.source.web.actions.adjust.base_url_change_in_files import AdjustBaseUrlChangeInFiles
from parallels.plesk.source.web.actions.adjust.disable_joomla_cache import DisableJoomlaCache
from parallels.plesk.source.web.actions.adjust.disable_prestashop_cache import DisablePrestashopCache
from parallels.plesk.source.web.actions.adjust.paths import AdjustPaths
from parallels.plesk.source.web.actions.adjust.site_name_change import AdjustSiteNameChange
from parallels.plesk.source.web.actions.check.check_apps import CheckApps
from parallels.plesk.source.web.actions.check.finish_check_apps import FinishCheckApps
from parallels.plesk.source.web.actions.check.start_check_apps import StartCheckApps
from parallels.plesk.source.web.actions.configure.applications import RetrieveApplications
from parallels.plesk.source.web.actions.configure.check_same_webspace import CheckSameWebspace
from parallels.plesk.source.web.actions.configure.connect import ConnectToSourceDomain
from parallels.plesk.source.web.actions.configure.deploy_web_rpc_agent import DeployWebRPCAgent
from parallels.plesk.source.web.actions.configure.document_root_and_url import RetrieveDocumentRootAndURL
from parallels.plesk.source.web.actions.configure.files_tree import RetrieveFilesTree
from parallels.plesk.source.web.actions.configure.finish import FinishGetSiteInfo
from parallels.plesk.source.web.actions.configure.initialize_site_info import InitializeSiteInfo
from parallels.plesk.source.web.actions.configure.target_site_info import RetrieveTargetSiteInfo
from parallels.plesk.source.web.actions.conflicts.database import ResolveDatabaseNameConflicts
from parallels.plesk.source.web.actions.conflicts.database_user import ResolveDatabaseUserNameConflicts
from parallels.plesk.source.web.actions.content.database.copy_database_content import CopyDatabaseContent
from parallels.plesk.source.web.actions.content.web.copy_content import CopyFiles
from parallels.plesk.source.web.actions.create_model import CreateModel
from parallels.plesk.source.web.actions.deploy.database import DeployDatabases
from parallels.plesk.source.web.actions.deploy.database_user import DeployDatabaseUsers
from parallels.plesk.source.web.actions.finish_migration import FinishMigration
from parallels.plesk.source.web.actions.read_migration_list import ReadMigrationList
from parallels.plesk.source.web.actions.register_wordpress import RegisterWordpress
from parallels.plesk.source.web.actions.remove_index_files import RemoveIndexFiles
from parallels.plesk.source.web.actions.remove_ssh_keys import RemoveSSHKeys
from parallels.plesk.source.web.actions.remove_web_rpc_agent import RemoveWebRPCAgent
from parallels.plesk.source.web.actions.start_migration import StartMigration
from parallels.plesk.source.web.actions.statistics.calc_folder_data_size import CalcFolderDataSize
from parallels.plesk.source.web.actions.statistics.finalize_get_site_info import FinalizeGetSiteInfoStatistics
from parallels.plesk.source.web.actions.statistics.finalize_transfer_site import FinalizeTransferSiteStatistics
from parallels.plesk.source.web.actions.statistics.get_source_php_version import GetSourcePhpVersion
from parallels.plesk.source.web.actions.statistics.mark_get_site_info_finished import MarkGetSiteInfoFinished
from parallels.plesk.source.web.actions.statistics.mark_transfer_site_finished import MarkTransferSiteFinished
from parallels.plesk.source.web.actions.statistics.source_is_windows import GetSourceIsWindows
from parallels.plesk.source.web.actions.statistics.start_get_site_info import StartGetSiteInfoStatistics
from parallels.plesk.source.web.actions.statistics.start_trasfer_site import StartTransferSiteStatistics
from parallels.plesk.source.web.actions.task_manager.add_tasks import AddTasksAction
from parallels.plesk.source.web.actions.task_manager.cancel_tasks import CancelTasksAction
from parallels.plesk.source.web.actions.task_manager.run_tasks import RunTasksAction
from parallels.plesk.source.web.actions.validate_databases import ValidateDatabases


class WorkflowBuilder(WorkflowBuilderBase):
    def create_workflow(self, global_context):
        """Create and return workflow object according given context

        :type global_context: parallels.core.global_context.GlobalMigrationContext
        :rtype: parallels.core.workflow.base_workflow.BaseWorkflow
        """
        workflow = BaseWorkflow()
        WorkflowExtension().extend_workflow(workflow)
        return workflow


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
        """
        # Get information from source actions
        workflow.add_shared_action(
            'get-site-info', CompoundAction(
                description=messages.ACTION_GET_SITE_INFO_DESCRIPTION
            )
        )
        workflow.get_shared_action('get-site-info').insert_action(
            'create-model', CreateModel()
        )
        workflow.get_shared_action('get-site-info').insert_action(
            'connect', ConnectToSourceDomain()
        )
        workflow.get_shared_action('get-site-info').insert_action(
            'retrieve-document-root', RetrieveDocumentRootAndURL()
        )
        workflow.get_shared_action('get-site-info').insert_action(
            'deploy-rpc-agent', DeployWebRPCAgent()
        )
        workflow.get_shared_action('get-site-info').insert_action(
            'get-source-php-version', GetSourcePhpVersion()
        )
        workflow.get_shared_action('get-site-info').insert_action(
            'get-source-is-windows', GetSourceIsWindows()
        )
        workflow.get_shared_action('get-site-info').insert_action(
            'check-same-site', CheckSameWebspace()
        )
        workflow.get_shared_action('get-site-info').insert_action(
            'retrieve-files-tree', RetrieveFilesTree()
        )
        workflow.get_shared_action('get-site-info').insert_action(
            'retrieve-applications', RetrieveApplications()
        )
        workflow.get_shared_action('get-site-info').insert_action(
            'finish-get-site-info', FinishGetSiteInfo()
        )

        # Copy content actions
        workflow.add_shared_action('copy-web-content', CompoundAction(
            description=messages.ACTION_COPY_WEB_FILES_DESCRIPTION
        ))
        workflow.get_shared_action('copy-web-content').insert_action(
            'remove-index-files', RemoveIndexFiles()
        )
        workflow.get_shared_action('copy-web-content').insert_action(
            'copy-files', CopyFiles()
        )

        workflow.add_shared_action('copy-db-content', CopyDatabaseContent())

        workflow.add_shared_action('copy-content', CompoundAction(
            description=messages.ACTION_COPY_CONTENT_DESCRIPTION,
        ))
        workflow.get_shared_action('copy-content').insert_action(
            'web', workflow.get_shared_action_pointer('copy-web-content')
        )
        workflow.get_shared_action('copy-content').insert_action(
            'database', workflow.get_shared_action_pointer('copy-db-content')
        )

        # Adjust application actions
        workflow.add_shared_action('adjust-applications', CompoundAction())
        workflow.get_shared_action('adjust-applications').insert_action(
            'adjust-paths', AdjustPaths()
        )
        workflow.get_shared_action('adjust-applications').insert_action(
            'adjust-application-database-host', AdjustApplicationDatabaseHost()
        )
        workflow.get_shared_action('adjust-applications').insert_action(
            'adjust-application-database-name', AdjustApplicationDatabaseName()
        )
        workflow.get_shared_action('adjust-applications').insert_action(
            'adjust-application-database-user', AdjustApplicationDatabaseUser()
        )
        workflow.get_shared_action('adjust-applications').insert_action(
            'adjust-site-name', AdjustSiteNameChange()
        )
        workflow.get_shared_action('adjust-applications').insert_action(
            'adjust-base-url-in-db', AdjustBaseUrlChangeInDB()
        )
        workflow.get_shared_action('adjust-applications').insert_action(
            'adjust-base-url-in-files', AdjustBaseUrlChangeInFiles()
        )
        workflow.get_shared_action('adjust-applications').insert_action(
            'disable-prestashop-cache', DisablePrestashopCache()
        )
        workflow.get_shared_action('adjust-applications').insert_action(
            'disable-joomla-cache', DisableJoomlaCache()
        )

        # Entry points:

        # 1) Get site info
        workflow.add_entry_point('get-site-info', EntryPointAction())
        workflow.get_path('get-site-info').insert_action(
            'initialize-site-info', InitializeSiteInfo()
        )
        workflow.get_path('get-site-info').insert_action(
            'retrieve-target-site-info', RetrieveTargetSiteInfo()
        )
        workflow.get_path('get-site-info').insert_action(
            'start-get-site-info-statistics', StartGetSiteInfoStatistics()
        )
        workflow.get_path('get-site-info').insert_action(
            'get-site-info', workflow.get_shared_action_pointer('get-site-info')
        )
        workflow.get_path('get-site-info').insert_action(
            'mark-get-site-info-finished', MarkGetSiteInfoFinished()
        )
        workflow.get_path('get-site-info').insert_action(
            'remove-web-agents', RemoveWebRPCAgent()
        )
        workflow.get_path('get-site-info').insert_action(
            'remove-ssh-keys', RemoveSSHKeys()
        )
        workflow.get_path('get-site-info').insert_action(
            'finalize-get-site-info-statistics', FinalizeGetSiteInfoStatistics()
        )
        workflow.get_path('get-site-info').register_overall_shutdown('remove-web-agents')
        workflow.get_path('get-site-info').register_overall_shutdown('remove-ssh-keys')
        workflow.get_path('get-site-info').register_overall_shutdown('finalize-get-site-info-statistics')

        # 2) Transfer site
        workflow.add_entry_point('transfer-site', EntryPointAction())
        workflow.get_path('transfer-site').insert_action(
            'read-migration-list', ReadMigrationList()
        )
        workflow.get_path('transfer-site').insert_action(
            'initialize-site-info', InitializeSiteInfo()
        )
        workflow.get_path('get-site-info').insert_action(
            'retrieve-target-site-info', RetrieveTargetSiteInfo()
        )
        workflow.get_path('transfer-site').insert_action(
            'start-transfer-site-statistics', StartTransferSiteStatistics()
        )
        workflow.get_path('transfer-site').insert_action(
            'start-migration', StartMigration()
        )
        workflow.get_path('transfer-site').insert_action(
            'get-site-info', workflow.get_shared_action_pointer('get-site-info')
        )
        workflow.get_path('transfer-site').insert_action(
            'validate-databases', ValidateDatabases()
        )
        workflow.get_path('transfer-site').insert_action(
            'resolve-database-name-conflicts', ResolveDatabaseNameConflicts()
        )
        workflow.get_path('transfer-site').insert_action(
            'resolve-database-user-name-conflicts', ResolveDatabaseUserNameConflicts()
        )
        workflow.get_path('transfer-site').insert_action('deploy-databases', DeployDatabases())
        workflow.get_path('transfer-site').insert_action('deploy-database-users', DeployDatabaseUsers())
        workflow.get_path('transfer-site').insert_action(
            'copy-content', workflow.get_shared_action_pointer('copy-content')
        )
        workflow.get_path('transfer-site').insert_action(
            'adjust-applications', workflow.get_shared_action_pointer('adjust-applications')
        )
        workflow.get_path('transfer-site').insert_action(
            'register-wordpress', RegisterWordpress()
        )
        workflow.get_path('transfer-site').insert_action(
            'calc-folder-data-size', CalcFolderDataSize()
        )
        workflow.get_path('transfer-site').insert_action(
            'mark-transfer-site-finished', MarkTransferSiteFinished()
        )
        workflow.get_path('transfer-site').insert_action(
            'remove-web-agents', RemoveWebRPCAgent()
        )
        workflow.get_path('transfer-site').insert_action(
            'remove-ssh-keys', RemoveSSHKeys()
        )
        workflow.get_path('transfer-site').insert_action(
            'finish-migration', FinishMigration()
        )
        workflow.get_path('transfer-site').insert_action(
            'finalize-transfer-site-statistics', FinalizeTransferSiteStatistics()
        )
        workflow.get_path('transfer-site').register_overall_shutdown('remove-web-agents')
        workflow.get_path('transfer-site').register_overall_shutdown('remove-ssh-keys')
        workflow.get_path('transfer-site').register_overall_shutdown('finish-migration')
        workflow.get_path('transfer-site').register_overall_shutdown('finalize-transfer-site-statistics')

        # 3) Task manager commands: add, cancel and run site migration tasks.
        # These commands are necessary for asynchronous integration with GUI.
        workflow.add_entry_point('run-tasks', EntryPointAction())
        workflow.get_path('run-tasks').insert_action('run-tasks', RunTasksAction())
        workflow.add_entry_point('add-tasks', EntryPointAction())
        workflow.get_path('add-tasks').insert_action('add-tasks', AddTasksAction())
        workflow.add_entry_point('cancel-tasks', EntryPointAction())
        workflow.get_path('cancel-tasks').insert_action('cancel-tasks', CancelTasksAction())

        # 4) Post-migration check commands: check-apps
        workflow.add_entry_point('check-apps', EntryPointAction())
        workflow.get_path('check-apps').insert_action('read-migration-list', ReadMigrationList())
        workflow.get_path('check-apps').insert_action('initialize-site-info', InitializeSiteInfo())
        workflow.get_path('check-apps').insert_action('retrieve-target-site-info', RetrieveTargetSiteInfo())
        workflow.get_path('check-apps').insert_action('start-check-apps', StartCheckApps())
        workflow.get_path('check-apps').insert_action('check-apps', CheckApps())
        workflow.get_path('check-apps').insert_action('finish-check-apps', FinishCheckApps())
