from logbroker.public.api.protos.common_pb2 import (
    Path, BoolOrDefaultValue, IntOrDefaultValue, StringOrDefaultValue, TopicProperties, Permissions
)
from logbroker.public.api.protos.config_manager_pb2 import (
    SingleModifyRequest, UpdateTopicRequest, CreateTopicRequest, GrantPermissionsRequest, AddTopicToYtDeliveryRequest
)

from saas.library.python.logbroker.common import get_one_of
from saas.library.python.logbroker.configuration.entities import LogbrokerEntity


class LogbrokerTopic(LogbrokerEntity):
    _PROP_TYPE_MAPPING = {
        'partitions_count': IntOrDefaultValue,
        'retention_period_sec': IntOrDefaultValue,
        'abc_service': StringOrDefaultValue,
        'abc_id': IntOrDefaultValue,
        'allow_unauthenticated_read': BoolOrDefaultValue,
        'allow_unauthenticated_write': BoolOrDefaultValue,
        'responsible': StringOrDefaultValue,
        'mailing_list': StringOrDefaultValue,
        'supported_format_version': IntOrDefaultValue,
        'supported_codecs': StringOrDefaultValue
    }
    _PROP_CLASS = TopicProperties

    @classmethod
    def make_create_request(cls, path, partitions_count=1, retention_period_sec=86400, **properties):
        properties['partitions_count'] = partitions_count
        properties['retention_period_sec'] = retention_period_sec
        return SingleModifyRequest(
            create_topic=CreateTopicRequest(path=Path(path=path), properties=cls._fill_properties(**properties))
        )

    def get_allow_unauthenticated_read(self):
        return get_one_of(self.describe().properties.allow_unauthenticated_read, 'variant')

    def set_allow_unauthenticated_read(self, value: bool):
        self._logbroker_client.execute_modify_commands([
            self.get_modification_request(
                allow_unauthenticated_write=value
            )
        ])

    def get_allow_unauthenticated_write(self):
        return get_one_of(self.describe().properties.allow_unauthenticated_write, 'variant')

    def set_allow_unauthenticated_write(self, value: bool):
        self._logbroker_client.execute_modify_commands([
            self.get_modification_request(
                allow_unauthenticated_write=value
            )
        ])

    allow_unauthenticated_read = property(
        get_allow_unauthenticated_read,
        set_allow_unauthenticated_read,
        None, 'Allow unauthenticated read from topic'
    )
    allow_unauthenticated_write = property(
        get_allow_unauthenticated_write,
        set_allow_unauthenticated_write,
        None, 'Allow unauthenticated  write to topic'
    )

    @property
    def partitions_count(self):
        return get_one_of(self.describe().properties.partitions_count, 'variant')

    @property
    def abc_service(self):
        return get_one_of(self.describe().properties.abc_service, 'variant')

    @property
    def abc_id(self):
        return get_one_of(self.describe().properties.abc_id, 'variant')

    @property
    def retention_period_sec(self):
        return get_one_of(self.describe().properties.retention_period_sec, 'variant')

    @property
    def responsible(self):
        responsible_str = get_one_of(self.describe().properties.retention_period_sec, 'variant')
        return [s.strip for s in responsible_str.split(',')]

    @property
    def supported_format_version(self) -> int:
        return get_one_of(self.describe().properties.supported_format_version, 'variant')

    @property
    def supported_codecs(self):
        codecs_str = get_one_of(self.describe().properties.supported_codecs, 'variant')
        return [s.strip for s in codecs_str.split(',')]

    @property
    def yt_deliveries(self):
        return self.describe().yt_deliveries

    def get_modification_request(self, **properties):
        return SingleModifyRequest(
            update_topic=UpdateTopicRequest(path=Path(path=self.path), properties=self._fill_properties(**properties))
        )

    def grant_permissions_request(self, permissions, subject, human_readable_subject_name=None):
        """
        :param permissions: List of ReadTopic,WriteTopic,ReadAsConsumer,ModifyPermissions,CreateResources,ModifyResources,ListResources,CreateReadRules,DescribeResources
        :param subject: {tvm-id}@tvm, {user-or-staff-group}@staff, svc_{abc-service}@staffor authenticated@well-know
        """
        permissions_dict = {
            'permission_names': permissions,
            'subject': subject
        }

        if subject != 'everyone':
            subject_name, subject_type = subject.split('@')
            permissions_dict['subject_type'] = subject_type
            permissions_dict['subject_name'] = subject_name

        if human_readable_subject_name:
            permissions_dict['subject_name'] = human_readable_subject_name

        return SingleModifyRequest(
            grant_permissions=GrantPermissionsRequest(
                path=Path(path=self.path),
                permissions=[Permissions(**permissions_dict)]
            )
        )

    def add_yt_delivery_request(self, delivery_path):
        return SingleModifyRequest(
            add_topic_to_yt_delivery=AddTopicToYtDeliveryRequest(
                topic=self.path,
                delivery=delivery_path
            )
        )
