import ntpath

from parallels.core import messages, MigrationError
from parallels.core.utils.file_utils import get_relative_path
from parallels.core.utils.paths import web_paths
from parallels.core.utils.paths.copy_web_content import BaseWebPathConverter
from parallels.plesk.source.plesk.server import PleskSourceServer


class WindowsSourceWebPathConverter(BaseWebPathConverter):
    """Class to convert abstract path descriptor to concrete path on source server"""

    def __init__(self, vhost_dir=None, is_rsync=False):
        self._vhost_dir = vhost_dir
        self._is_rsync = is_rsync

    def expand(self, path, server):
        """Convert abstract path descriptor to concrete absolute path for source server

        :type path: parallels.core.utils.web_paths.WebHostingPath
        :type server: parallels.core.connections.source_server.SourceServer
        :rtype: str | unicode
        """
        if isinstance(path, web_paths.AbsolutePath):
            if self._is_rsync:
                rsync_share, rsync_share_relative_path = self._get_rsync_share_and_relative_path(
                    path.absolute_path,
                    server
                )
                if rsync_share is None or rsync_share_relative_path is None:
                    raise MigrationError(messages.SOURCE_WEB_PATH_ERROR_NO_RSYNC_SHARE.format(
                        absolute_path=path.absolute_path, server_description=server.description()
                    ))
                return '%s/%s' % (rsync_share, rsync_share_relative_path.replace('\\', '/'))
            return path.absolute_path
        if isinstance(path, web_paths.VirtualHostsPath):
            if self._is_rsync:
                return 'vhosts/%s' % path.relative_path.replace('\\', '/')
            if self._vhost_dir is None:
                raise MigrationError(messages.SOURCE_WEB_PATH_ERROR_NO_VHOST.format(
                    relative_path=path.relative_path, server_description=server.description()
                ))
            return ntpath.join(self._vhost_dir, path.relative_path)
        else:
            assert False, messages.UNSUPPORTED_SOURCE_WEB_PATH_TYPE

    @staticmethod
    def _get_rsync_share_and_relative_path(absolute_path, server):
        """Retrieve rsync share to which the give path belongs and path to the same location, related to this share

        :type absolute_path: str
        :type server: parallels.core.connections.source_server.SourceServer
        """
        if not isinstance(server, PleskSourceServer):
            return None, None
        if server.plesk_version < (17, 0):
            return None, None
        # check if given path belongs to 'extensions' share
        relative_path = get_relative_path(absolute_path, server.get_extensions_var_dir(), server.is_windows())
        if relative_path is not None:
            return 'extensions', relative_path
        # share is not found
        return None, None
