from parallels.core.utils.common import default
from parallels.core.utils.entity import Entity


class CopyContentItem(Entity):
    def __init__(
        self, source_path, target_path, skip_if_source_not_exists=False, exclude=None,
        source_system_user_login=None, source_system_user_uid=None, source_system_user_gid=None
    ):
        """Init content item to copy

        :type source_path: parallels.core.utils.web_paths.WebHostingPath
        :type target_path: parallels.core.utils.web_paths.WebHostingPath
        :type skip_if_source_not_exists: bool
        :type exclude: list[str | unicode]
        :type source_system_user_login: str | unicode | None
        :type source_system_user_uid: str | unicode | None
        :type source_system_user_gid: str | unicode | None
        """
        self._source_path = source_path
        self._target_path = target_path
        self._skip_if_source_not_exists = skip_if_source_not_exists
        self._exclude = default(exclude, [])
        self._source_system_user_login = source_system_user_login
        self._source_system_user_uid = source_system_user_uid
        self._source_system_user_gid = source_system_user_gid

    @property
    def source_path(self):
        """Source path of the web files to be copied

        :rtype: parallels.core.utils.web_paths.WebHostingPath
        """
        return self._source_path

    @property
    def target_path(self):
        """Target path of the web files to be copied

        :rtype: parallels.core.utils.web_paths.WebHostingPath
        """
        return self._target_path

    @property
    def skip_if_source_not_exists(self):
        """
        :rtype: bool
        """
        return self._skip_if_source_not_exists

    @property
    def exclude(self):
        """List of files to exclude

        :rtype: list[str | unicode]
        """
        return self._exclude

    @property
    def source_system_user_login(self):
        """Login of system user that owns these files on the source server.

        Should be specified if it differs from main system user of subscription.
        Mutually exclusive with 'source_system_user_uid' and 'source_system_user_gid' properties.

        :rtype: str | unicode | None
        """
        return self._source_system_user_login

    @property
    def source_system_user_uid(self):
        """UID (user id) of system user that owns these files on the source server.

        Should be specified if it differs from main system user of subscription.
        Mutually exclusive with 'source_system_user_login' property.
        If that property is set, 'source_system_user_gid' property expected to be set too.

        :rtype: str | unicode | None
        """
        return self._source_system_user_uid

    @property
    def source_system_user_gid(self):
        """GID (group id) of system user that owns these files on the source server.

        Should be specified if it differs from main system user of subscription.
        Mutually exclusive with 'source_system_user_login' property.
        If that property is set, 'source_system_user_uid' property is expected to be set too.

        :rtype: str | unicode | None
        """
        return self._source_system_user_gid


class CopyWebContentItem(CopyContentItem):
    def __init__(
        self, source_path, target_path, skip_if_source_not_exists=False, exclude=None,
        domain_name=None, fix_application_paths=True,
        source_system_user_login=None, source_system_user_uid=None, source_system_user_gid=None
    ):
        """Init web content item to copy

        :type source_path: parallels.core.utils.web_paths.WebHostingPath
        :type target_path: parallels.core.utils.web_paths.WebHostingPath
        :type skip_if_source_not_exists: bool
        :type exclude: list[str | unicode]
        :type domain_name: str
        :type fix_application_paths: bool
        """
        super(CopyWebContentItem, self).__init__(
            source_path, target_path, skip_if_source_not_exists, exclude,
            source_system_user_login, source_system_user_uid, source_system_user_gid
        )
        self._domain_name = domain_name
        self._fix_application_paths = fix_application_paths

    @property
    def domain_name(self):
        """Domain name this content is related to. Could be None

        :rtype: str | unicode | None
        """
        return self._domain_name

    @property
    def fix_application_paths(self):
        """Whether to fix application paths fo this item

        When set to true, migrator takes source path, destination path, and if they are not equal
        then replaces the source path with the destination one in web content files.
        So, it makes sense to set it to true for document root, for which we can have absolute references
        in site's code and configuration files. It does not make much sense to set it to true for
        service files, like logs, .Security files, protected directories settings in Plesk, etc.

        :rtype: bool
        """
        return self._fix_application_paths


class BaseWebPathConverter(object):
    """Class to convert abstract path descriptor to concrete absolute path"""

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

        :type path: parallels.core.utils.web_paths.WebHostingPath
        :rtype: str | unicode
        """
        raise NotImplementedError()
