import load.projects.cloud.loadtesting.server.admin.proto.agent_versions_pb2 as agent_versions_pb2
import load.projects.cloud.loadtesting.server.admin.proto.agent_versions_pb2_grpc as agent_versions_pb2_grpc

from load.projects.cloud.loadtesting.db import DB
from load.projects.cloud.loadtesting.db.tables import AgentVersionStatus
from load.projects.cloud.loadtesting.server.admin.implementations.versions import db_version_from_message, \
    message_from_db_version


class AgentVersionsServicer(agent_versions_pb2_grpc.AgentVersionsServicer):
    def Add(self, version: agent_versions_pb2.Version, context):
        """
        grpcurl -plaintext -d '{"id": "image_id", "revision": "arc_revision", "hash": "arc_hash",
        "description": "description", "status": "STATUS" }' localhost:50055 AgentVersions/Add

        where STATUS is one of ['TARGET', 'ACTUAL', 'DEPRECATED', 'OUTDATED', 'TESTING']
        """
        assert version.status, "Status required."
        assert version.id, "Id required."
        db_version = db_version_from_message(version)
        with DB() as db:
            db.agent_version.add(db_version)
            if db_version.status == AgentVersionStatus.TARGET.value:
                db.agent_version.switch_target(db_version)
            return message_from_db_version(db_version)

    def SwitchTarget(self, request: agent_versions_pb2.SwitchTargetRequest, context):
        """
        grpcurl -plaintext -d '{"id": "image_id"}' localhost:50055 AgentVersions/SwitchTarget
        """
        with DB() as db:
            new_target = db.agent_version.get(request.id)
            assert new_target, "Version not found."
            db.agent_version.switch_target(new_target)
            return message_from_db_version(new_target)

    def ChangeStatus(self, request: agent_versions_pb2.ChangeStatusRequest, context):
        """
        grpcurl -plaintext -d '{"id": "image_id", "status": "ACTUAL"}' localhost:50055 AgentVersions/ChangeStatus
        """
        with DB() as db:
            version = db.agent_version.get(request.id)
            assert version, "Version not found."
            db.agent_version.change_status(version,
                                           AgentVersionStatus(agent_versions_pb2.VersionStatus.Name(request.status)))
            return message_from_db_version(version)

    def DeprecateUpTo(self, request: agent_versions_pb2.DeprecateUpToRequest, context):
        """
        grpcurl -plaintext -d '{"id": "image_id"}' localhost:50055 AgentVersions/DeprecateUpTo
        """
        with DB() as db:
            new_deprecated_db = db.agent_version.deprecate_up_to(request.id)
            return agent_versions_pb2.VersionsList(
                versions=[
                    message_from_db_version(v)
                    for v in new_deprecated_db
                ]
            )

    def OutdateUpTo(self, request: agent_versions_pb2.OutdateUpToRequest, context):
        """
        grpcurl -plaintext -d '{"id": "image_id"}' localhost:50055 AgentVersions/OutdateUpTo
        """
        with DB() as db:
            new_outdated_db = db.agent_version.outdate_up_to(request.id)
            return agent_versions_pb2.VersionsList(
                versions=[
                    message_from_db_version(v)
                    for v in new_outdated_db
                ]
            )
