# Copyright (C) 2022-2023 HERE Global B.V. and its affiliate(s).
# All rights reserved.
#
# This software and other materials contain proprietary information
# controlled by HERE and are protected by applicable copyright legislation.
# Any use and utilization of this software and other materials and
# disclosure to any third parties is conditional upon having a separate
# agreement with HERE for the access, use, utilization or disclosure of this
# software. In the absence of such agreement, the use of the software is not
# allowed.

"""HERE platform Artifact abstraction."""

from typing import TYPE_CHECKING, Optional

from here.platform.api.artifact_api import ArtifactApi
from here.platform.utils import JsonDictDocument

if TYPE_CHECKING:
    from here.platform.platform import Platform


class ArtifactConfiguration(JsonDictDocument):
    """
    A JSON document for artifact configuration used in APIs loaded into a ``Dict``.
    """

    @property
    def group_id(self) -> Optional[str]:
        """Group ID in the artifact response"""
        return str(self.json["groupId"]) if "groupId" in self.json else None

    @property
    def artifact_id(self) -> Optional[str]:
        """Artifact ID in the artifact response"""
        return str(self.json["artifactId"]) if "artifactId" in self.json else None

    @property
    def version(self) -> Optional[str]:
        """Version in the artifact response"""
        return str(self.json["version"]) if "version" in self.json else None

    @property
    def created(self) -> Optional[str]:
        """Created date in the artifact response"""
        return str(self.json["created"]) if "created" in self.json else None

    @property
    def updated(self) -> Optional[str]:
        """Updated date in the artifact response"""
        return str(self.json["updated"]) if "updated" in self.json else None

    @property
    def files(self) -> Optional[str]:
        """Files in the artifact response"""
        return str(self.json["files"]) if "files" in self.json else None


class Artifact:
    """
    HERE platform Artifact abstraction.
    """

    def __init__(
        self,
        hrn: str,
        configuration: ArtifactConfiguration,
        platform: "Platform",
    ):
        """
        Initiate a new artifact object with the given configuration.

        :param configuration: an instance of ArtifactConfiguration
        :param hrn: hrn of the artifact
        :param platform: platform object
        """
        self.hrn: str = hrn
        self.platform = platform
        self.group_id = configuration.group_id
        self.artifact_id = configuration.artifact_id
        self.version = configuration.version
        self.created = configuration.created
        self.updated = configuration.updated
        self.files = configuration.files
        self.artifact_api: ArtifactApi = platform.artifact_api

    def update_permission(self, body: dict) -> bool:
        """
        READ grants 'readResource', MODIFY grants 'modifyResource', SHARE grants 'shareResource'.
        :param body: a dictionary with permissions.
        :return: response from the API.
        """

        return self.artifact_api.update_artifact_permission(artifact_hrn=self.hrn, body=body)

    def get_file(self, file_name: str) -> bytes:
        """
        Return the binary data of file linked to artifact.

        :param file_name: The path to artifact file
        :return: response from the API.
        """
        return self.artifact_api.get_artifact_file(artifact_hrn=self.hrn, file_name=file_name)

    def get_file_from_archive(self, archive_file: str, file_in_archive: str) -> bytes:
        """
        Returns the binary data of a file stored in archive.

        :param archive_file: The name of artifact archive. Supported archive types are zip and jar
        :param file_in_archive: Relative path of file in archive
        :return: response from the API.
        """

        return self.artifact_api.get_artifact_file_from_archive(
            artifact_hrn=self.hrn,
            archive_file=archive_file,
            file_in_archive=file_in_archive,
        )

    def put_file(self, file_name: str, body: bytes) -> bool:
        """
        Upload the file and linked to artifact. Requires permission to 'modifyResource'
        for the given HRN.

        :param body: Data to be uploaded
        :param file_name: The path to artifact file
        :return: response from the API.
        """

        return self.artifact_api.put_artifact_file(
            artifact_hrn=self.hrn, file_name=file_name, body=body
        )

    def delete_file(self, file_name: str) -> bool:
        """
        Delete file from the artifact. for the given HRN

        :param file_name: The path to artifact file
        :return: response from the API.
        """

        return self.artifact_api.delete_artifact_file(artifact_hrn=self.hrn, file_name=file_name)
