from eolymp.community import member_pb2
from eolymp.community.attribute_pb2 import Attribute
from eolymp.community.member_service_http import MemberServiceClient
from eolymp.community.member_service_pb2 import DescribeMemberInput, DeleteMemberInput, UpdateMemberInput, \
    ListMembersInput, CreateMemberInput
from eolymp.community.member_user_pb2 import User
from eolymp.wellknown import expression_pb2

from peolymp.abstract import AbstractAPI


class CommunityAPI(AbstractAPI):
    def __init__(self, space):
        super(CommunityAPI, self).__init__(space)
        self.client = MemberServiceClient(self.http_client, url=self.get_url())

    def get_member(self, member_id):
        return self.client.DescribeMember(DescribeMemberInput(member_id=member_id, extra=[4])).member

    def get_members(self):
        def get_members(offset, size):
            return self.client.ListMembers(request=ListMembersInput(offset=offset, size=size))

        return self.get_many(get_members)

    def delete_member(self, member_id):
        return self.client.DeleteMember(DeleteMemberInput(member_id=member_id, force_delete=True))

    def delete_all_members(self):
        for member in self.get_members():
            self.delete_member(member.id)

    def clear_members(self):
        members = self.get_members()
        for member in members:
            self.delete_member(member.id)

    def make_members_incomplete(self):
        members = self.get_members()
        print(len(members))
        c = 0
        n = len(members)
        for member in members:
            c += 1
            m = member_pb2.Member(registered=False)
            member.registered = False
            if member.status == 2:
                continue
            print(member)
            print(self.client.UpdateMember(
                UpdateMemberInput(patch=[UpdateMemberInput.REGISTERED], member_id=member.id,
                                  member=m)))

            print((c * 100) // n)

    def find_member(self, user_id):
        member_exp = expression_pb2.ExpressionID(value=user_id)
        setattr(member_exp, 'is', 1)
        member_filter = ListMembersInput.Filter(user_id=[member_exp])
        m = self.client.ListMembers(ListMembersInput(filters=member_filter))
        if m.total == 1:
            return m.items[0]
        return None

    def add_member(self, nickname, name, out_of_competition=False):
        user = User(issuer="https://accounts.eolymp.com", nickname=nickname)
        values = [
            Attribute.Value(attribute_key='name', string=name)]
        member = member_pb2.Member(name=name, active=True, attributes=values,
                                   unofficial=out_of_competition, user=user)
        result = self.client.CreateMember(CreateMemberInput(member=member))
        return result.member_id

    def create_manual_member(self, name, username, password, string_attributes=None, number_attributes=None,
                             registered=True, out_of_competition=False,
                             incomplete=False):
        # print('Incomplete', incomplete)
        if string_attributes is None:
            string_attributes = {}
        user = User(issuer="https://api.eolymp.com/spaces/" + self.space_id, nickname=username, password=password,
                    email="test+" + username + "@uoi.ua", country="ua")
        values = []
        if string_attributes:
            for atr in string_attributes:
                values += [
                    Attribute.Value(attribute_key=atr, string=string_attributes[atr])
                ]
        if number_attributes:
            for atr in number_attributes:
                values += [
                    Attribute.Value(attribute_key=atr, number=int(number_attributes[atr]))
                ]
        print(values)
        member = member_pb2.Member(inactive=not registered, attributes=([] if incomplete else values),
                                   unofficial=out_of_competition, user=user)
        result = self.client.CreateMember(CreateMemberInput(member=member))
        # print(result)
        return result.member_id

    def change_name(self, member_id, name):
        self.client.UpdateMember(UpdateMemberInput(patch=[UpdateMemberInput.NAME],
                                                   member_id=member_id,
                                                   member=member_pb2.Member(name=name)))
