from ..cryption import cryption
from ..tools import tools
from ..message import message
from ..maker import maker
from ..handler import handler
from requests import get, post
from random import choice, randint
from time import time
from pathlib import Path

class methods:

    def __init__(self, auth):
        self.auth = auth
        self.hs = handler(auth).hand_shake
        self.method = maker(auth).method
        self.crypto = cryption(auth)
        self.got_messages_update = []
        self.filters = {
            'chat_filter': [],
            'message_filter': []
        }
        del auth

    def add_filter(self, chat_filter = [], message_filter = []):
        self.filters['chat_filter'] = chat_filter
        self.filters['message_filter'] = message_filter

    def on_message(self):
        for recv in self.hs():
            if not message(recv).chat_type() in self.filters['chat_filter'] and not message(recv).message_type() in self.filters['message_filter']:
                yield recv
            else:
                continue

    def get_chat_update(self, chat_id):
        return self.method(
            'getMessagesUpdates',
            {
                'object_guid': chat_id,
                'state': str(round(time()) - 200)
            }
        )['updated_messages']

    def get_chats_update(self):
        while True:
            chats_update = self.method('getChatsUpdates', {'state': str(round(time()) - 200)})['chats'][0]
            if not message(chats_update).message_id() in self.got_messages_update:
                if not message(chats_update).chat_type() in self.filters['chat_filter'] and not message(chats_update).message_type() in self.filters['message_filter']:
                    self.got_messages_update.append(message(chats_update).message_id())
                    return chats_update
                else:
                    continue
            else:
                continue

    def send_text(self, chat_id, custom_text, message_id = None):
        metadata = tools.check_metadata(custom_text)
        data = {
            'object_guid': chat_id,
            'rnd': str(randint(10000000, 999999999)),
            'text': metadata[1].strip(),
            'reply_to_message_id': message_id,
        }
        if metadata[0] != []:
            data['metadata'] = {'meta_data_parts': metadata[0]}
        return self.method('sendMessage', data)

    def reply(self, data, custom_text):
        msg = message(data)
        return self.send_text(
            msg.chat_id(),
            custom_text,
            msg.message_id()
        )

    def send_image(self, chat_id, file, caption = None, message_id = None, thumbnail = None):
        req = self.file_upload(file)
        size = tools.get_image_size(open(file,'rb').read() if not 'http' in file else get(file).content)
        metadata = tools.check_metadata(caption)
        data = {
            'file_inline': {
                'dc_id': req[0]['dc_id'],
                'file_id': req[0]['id'],
                'type':'Image',
                'file_name': file if not 'http' in file else f'pyrubi {randint(1, 100)}.png',
                'size': tools.get_file_size(file),
                'mime': 'png',
                'access_hash_rec': req[1],
                'width': size[0],
                'height': size[1],
                'thumb_inline': tools.get_thumbnail(open(file,'rb').read() if thumbnail == None and not 'http' in file else open(thumbnail,'rb').read() if not 'http' in file else get(file).content).decode('utf-8')
            },
            'object_guid': chat_id,
            'rnd': str(randint(100000,999999999)),
            'reply_to_message_id': message_id,
            'text': metadata[1]
        }
        if metadata[0] != []:
            data['metadata'] = {'meta_data_parts': metadata[0]}
        return self.method('sendMessage', data)

    def send_video(self, chat_id, file, caption = None, message_id = None):
        req = self.file_upload(file)
        metadata = tools.check_metadata(caption)
        data = {
            'file_inline': {
                'file_id': req[0]['id'],
                'mime': 'mp4',
                'dc_id': req[0]['dc_id'],
                'access_hash_rec': req[1],
                'file_name': file if not 'http' in file else f'pyrubi {randint(1, 100)}.mp4',
                'thumb_inline': '/9j/4AAQSkZJRgABAQAAAQABAAD/4gIoSUNDX1BST0ZJTEUAAQEAAAIYAAAAAAIQAABtbnRyUkdC\nIFhZWiAAAAAAAAAAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAA\nAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlk\nZXNjAAAA8AAAAHRyWFlaAAABZAAAABRnWFlaAAABeAAAABRiWFlaAAABjAAAABRyVFJDAAABoAAA\nAChnVFJDAAABoAAAAChiVFJDAAABoAAAACh3dHB0AAAByAAAABRjcHJ0AAAB3AAAADxtbHVjAAAA\nAAAAAAEAAAAMZW5VUwAAAFgAAAAcAHMAUgBHAEIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFhZWiAA\nAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAAJKAAAA+EAAC2z3Bh\ncmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABYWVogAAAAAAAA9tYAAQAAAADT\nLW1sdWMAAAAAAAAAAQAAAAxlblVTAAAAIAAAABwARwBvAG8AZwBsAGUAIABJAG4AYwAuACAAMgAw\nADEANv/bAEMADQkKCwoIDQsKCw4ODQ8TIBUTEhITJxweFyAuKTEwLiktLDM6Sj4zNkY3LC1AV0FG\nTE5SU1IyPlphWlBgSlFST//bAEMBDg4OExETJhUVJk81LTVPT09PT09PT09PT09PT09PT09PT09P\nT09PT09PT09PT09PT09PT09PT09PT09PT09PT//AABEIAGQAOAMBIgACEQEDEQH/xAAWAAEBAQAA\nAAAAAAAAAAAAAAAAAQf/xAAXEAEBAQEAAAAAAAAAAAAAAAAAAREx/8QAFQEBAQAAAAAAAAAAAAAA\nAAAAAAH/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oADAMBAAIRAxEAPwDMFRRAwACiAACiwAAEQqKi\nqtEAU0QRQADqKBgCCKixVDgYIAIFCiqgAKAiBQqiACixFgACIFCqIAKLAAARCFBRABX/2Q==\n',
                'width': 240,
                'height': 240,
                'time': tools.get_video_duration(file),
                'size': tools.get_file_size(file),
                'type': 'Video'
            },
            'object_guid': chat_id,
            'rnd': str(randint(100000,999999999)),
            'reply_to_message_id': message_id,
            'text': metadata[1]
        }
        if metadata[0] != []:
            data['metadata'] = {'meta_data_parts': metadata[0]}
        return self.method('sendMessage', data)

    def send_gif(self, chat_id, file, caption = None, message_id = None):
        req = self.file_upload(file)
        metadata = tools.check_metadata(caption)
        data = {
            'file_inline': {
                'file_id': req[0]['id'],
                'mime': 'mp4',
                'dc_id': req[0]['dc_id'],
                'access_hash_rec': req[1],
                'file_name': file if not 'http' in file else f'pyrubi {randint(1, 100)}.mp4',
                'width': 240,
                'height': 240,
                'time': tools.get_video_duration(file),
                'size': tools.get_file_size(file),
                'type': 'Gif',
                'is_round': False,
            },
            'object_guid': chat_id,
            'rnd': str(randint(100000,999999999)),
            'reply_to_message_id': message_id,
            'text': metadata[1]
        }
        if metadata[0] != []:
            data['metadata'] = {'meta_data_parts': metadata[0]}
        return self.method('sendMessage',data)

    def send_voice(self, chat_id, file, caption = None, message_id = None, time = None):
        req = self.file_upload(file)
        metadata = tools.check_metadata(caption)
        data = {
            'file_inline': {
                'dc_id': req[0]['dc_id'],
                'file_id': req[0]['id'],
                'type': 'Voice',
                'file_name': file if not 'http' in file else f'pyrubi {randint(1, 100)}.ogg',
                'size': tools.get_file_size(file),
                'time': int(tools.get_voice_duration(open(file,'rb').read()) if time == None else time) * 1000 if not 'http' in file else 1,
                'mime': 'ogg',
                'access_hash_rec': req[1],
            },
            'object_guid': chat_id,
            'rnd': str(randint(100000,999999999)),
            'reply_to_message_id': message_id,
            'text': metadata[1]
        }
        if metadata[0] != []:
            data['metadata'] = {'meta_data_parts': metadata[0]}
        return self.method('sendMessage', data)

    def send_music(self, chat_id, file, caption = None, message_id = None):
        req = self.file_upload(file)
        metadata = tools.check_metadata(caption)
        data = {
            'file_inline': {
                'file_id': req[0]['id'],
                'mime': 'mp3',
                'dc_id': req[0]['dc_id'],
                'access_hash_rec': req[1],
                'file_name': file if not 'http' in file else f'pyrubi {randint(1, 100)}.mp3',
                'width': 0,
                'height': 0,
                'time': tools.get_voice_duration(open(file,'rb').read()) if not 'http' in file else 1,
                'size': tools.get_file_size(file),
                'type': 'Music',
                'music_performer': tools.get_music_artist(file) if not 'http' in file else 'Pyrubi Library',
                'is_round': False
            },
            'is_mute': False,
            'object_guid': chat_id,
            'text': metadata[1],
            'rnd': str(randint(100000,999999999)),
            'reply_to_message_id': message_id
        }
        if metadata[0] != []:
            data['metadata'] = {'meta_data_parts': metadata[0]}
        return self.method('sendMessage', data)

    def send_file(self, chat_id, file, caption = None, message_id = None, mime=None):
        req = self.file_upload(file)
        metadata = tools.check_metadata(caption)
        data = {
            'file_inline': {
                'dc_id': req[0]['dc_id'],
                'file_id': req[0]['id'],
                'type': 'File',
                'file_name': file if not 'http' in file else f'pyrubi {randint(1, 100)}.{mime or tools.get_mime_from_url(file)}',
                'size': tools.get_file_size(file),
                'mime': file.split('.')[-1] if not 'http' in file else mime or tools.get_mime_from_url(file),
                'access_hash_rec': req[1]
            },
            'object_guid': chat_id,
            'rnd': str(randint(100000,999999999)),
            'reply_to_message_id': message_id,
            'text': metadata[1]
        }
        if metadata[0] != []:
            data['metadata'] = {'meta_data_parts': metadata[0]}
        return self.method('sendMessage', data)

    def send_sticker(self, chat_id, message_id = None):
        stickers = choice(self.method('getMyStickerSets',{})['sticker_sets'])
        return self.method(
            'sendMessage',
            {
                'sticker': choice(stickers['top_stickers']),
                'object_guid': chat_id,
                'rnd': str(randint(100000,999999999)),
                'reply_to_message_id': message_id
            }
        )

    def send_poll(self, chat_id, text_question = None, options = [], message_id = None, multiple_answers = False, anonymous = True,  quiz = False):
        return self.method(
            'createPoll',
            {
                'allows_multiple_answers': multiple_answers,
                'correct_option_index': None,
                'is_anonymous': anonymous,
                'object_guid': chat_id,
                'options': options if len(options) == 2 else ['This poll was created with "Pyrubi Library"', 'حداقل باید دو گزینه برای نظر سنجی بگزارید !'],
                'question': text_question if text_question != None else 'هیچ متنی تنظیم نشده است !',
                'reply_to_message_id': message_id,
                'rnd': randint(100000000, 999999999),
                'type': 'Quiz' if quiz else 'Regular'
            }
        )

    def vote_poll(self, poll_id, selection_index : str):
        return self.method(
            'votePoll',
            {
                'poll_id': poll_id,
                'selection_index': selection_index
            }
        )

    def get_poll_status(self, poll_id):
        return self.method('getPollStatus', {'poll_id': poll_id})

    def get_poll_option_voters(self, poll_id, selection_index : str, start_id = None):
        return self.method(
            'getPollOptionVoters',
            {
                'poll_id': poll_id,
                'selection_index': selection_index,
                'start_id': start_id
            }
        )

    def send_message_api_call(self, chat_id, text, message_id, button_id):
        return self.method(
            'sendMessageAPICall',
            {
                'text': text,
                'object_guid': chat_id,
                'message_id': message_id,
                'aux_data': {'button_id': button_id}
            }
        )

    def send_chat_activity(self, chat_id, action):
        return self.method(
            'sendChatActivity',
            {
                'object_guid': chat_id,
                'activity': action
            }
        )

    def edit_message(self, chat_id, new_text, message_id):
        metadata = tools.check_metadata(new_text)
        data = {
            'object_guid': chat_id,
            'text': metadata[1].strip(),
            'message_id': message_id,
        }
        if metadata[0] != []:
            data['metadata'] = {'meta_data_parts': metadata[0]}
        return self.method('editMessage', data)['message_update']

    def forward_message(self, from_chat_id, message_ids, to_chat_id):
        return self.method(
            'forwardMessages',
            {
                'from_object_guid': from_chat_id,
                'message_ids': message_ids,
                'rnd': str(randint(100000,999999999)),
                'to_object_guid': to_chat_id
            }
        )

    def resend_message(self, chat_id, file_inline, caption = None, message_id = None):
        metadata = tools.check_metadata(caption)
        data = {
            'file_inline': file_inline,
            'object_guid': chat_id,
            'rnd': str(randint(100000,999999999)),
            'reply_to_message_id': message_id,
            'text': metadata[1]
        }
        if metadata[0] != []:
            data['metadata'] = {'meta_data_parts': metadata[0]}
        return self.method(
            'sendMessage',
            data
        )

    def pin_message(self, chat_id, message_id):
        return self.method(
            'setPinMessage',
            {
                'object_guid': chat_id,
                'message_id': message_id,
                'action': 'Pin'
            }
        )

    def unpin_message(self, chat_id, message_id):
        return self.method(
            'setPinMessage',
            {
                'object_guid': chat_id,
                'message_id': message_id,
                'action': 'Unpin'
            }
        )

    def search_message(self, chat_id, text):
        return self.method(
            'searchChatMessages',
            {
                'object_guid': chat_id,
                'search_text': text,
                'type':'Text'
            }
        )['message_ids']

    def seen_message(self, chat_id, message_id):
        return self.method('seenChats', {'seen_list': {chat_id: int(message_id)}})

    def delete_message(self, chat_id, message_ids = [], type = 'Global'):
        return self.method(
            'deleteMessages',
            {
                'object_guid': chat_id,
                'message_ids': message_ids,
                'type': type
            }
        )['message_updates']

    def get_chat_messages(self, chat_id, middle_message_id):
        return self.method(
            'getMessagesInterval',
            {
                'object_guid':chat_id,
                'middle_message_id':middle_message_id
            }
        )['messages']

    def get_messages_info(self, chat_id, messages_ids = []):
        return self.method(
            'getMessagesByID',
            {
                'object_guid': chat_id,
                'message_ids': messages_ids
            }
        )['messages']

    def get_link_info(self, url):
        return self.method('getLinkFromAppUrl', {'app_url': url})['link']['open_chat_data']

    def get_post_info_by_link(self, post_link):
        """This method will be removed in the next update !"""
        return self.method('getLinkFromAppUrl', {'app_url': post_link})['link']['open_chat_data']

    def get_chats(self, start_id = None):
        return self.method('getChats', {'start_id': start_id})

    def search_chats(self, text):
        return self.method('searchGlobalObjects',{'search_text': text})['objects']

    def report_chat(self, chat_id, report_description, message_id = None):
        chat_type = tools.get_chat_type_by_id(chat_id)
        return self.method(
            'reportObject',
            {
                'object_guid': chat_id,
                'report_description': report_description, 
                'report_type_object': chat_type, 
                'report_type': 100,
                'meesage_id': message_id
            }
        )

    def get_chat_info(self, chat_id):
        data = tools.get_chat_type_by_id(chat_id)
        return self.method(f'get{data}Info',{f'{data.lower()}_guid': chat_id})
        
    def get_chat_preview_by_link(self, chat_link):
        return self.method(
            'groupPreviewByJoinLink' if 'joing' in chat_link else 'channelPreviewByJoinLink',
            {'hash_link': chat_link.split('/')[-1]}
        )

    def get_abs_chats(self, chat_ids = []):
        return self.method('getAbsObjects', {'objects': chat_ids})

    def get_chat_info_by_username(self, username):
        return self.method('getObjectByUsername', {'username': username.replace('@', '')})

    def get_chat_last_message(self, chat_id):
        return self.get_chat_info(chat_id)['chat']['last_message']

    def get_chat_last_message_id(self, chat_id):
        return self.get_chat_last_message(chat_id)['message_id']

    def delete_chat_history(self, chat_id):
        return self.method(
            'deleteChatHistory',
            {
                'object_guid': chat_id,
                'last_message_id': self.get_last_chat_message_id(chat_id)
            }
        )['chat_update']

    def delete_user_chat(self, user_id, last_deleted_message_id):
        return self.method(
            'deleteUserChat',
            {
                'user_guid': user_id,
                'last_deleted_message_id': last_deleted_message_id
            }
        )

    def add_group_members(self, group_id, member_ids = []):
        return self.method(
            'addGroupMembers',
            {
                'group_guid': group_id,
                'member_guids': member_ids
            }
        )

    def add_channel_members(self, channel_id, member_ids = []):
        return self.method(
            'addChannelMembers',
            {
                'channel_guid': channel_id,
                'member_guids': member_ids
            }
        )

    def ban_group_member(self, group_id, member_id):
        return self.method(
            'banGroupMember',
            {
                'group_guid': group_id,
                'member_guid': member_id,
                'action': 'Set'
            }
        )

    def get_banned_members(self, chat_id, start_id = None):
        return self.method(
            f'getBanned{tools.get_chat_type_by_id(chat_id)}Members',
            {
                f'{tools.get_chat_type_by_id(chat_id).lower()}_guid': chat_id,
                'start_id': start_id
            }
        )['in_chat_members']

    def set_group_access(self, group_id, view_members = False, view_admins = False ,send_message = False, add_member = False):
        access = []
        if view_members:
            access.append('ViewMembers')
        if view_admins:
            access.append('ViewAdmins')
        if send_message:
            access.append('SendMessages')
        if add_member:
            access.append('AddMember')
        return self.method(
            'setGroupDefaultAccess',
            {
                'access_list': access,
                'group_guid': group_id
            }
        )

    def get_group_members(self, group_id, start_id = None):
        return self.method(
            'getGroupAllMembers',
            {
                'group_guid': group_id,
                'start_id': start_id
            }
        )['in_chat_members']

    def get_group_admins(self, group_id, only_ids = True):
        data = self.method('getGroupAdminMembers', {'group_guid': group_id})
        return [i['member_guid'] for i in data['in_chat_members']] if only_ids else data['in_chat_members']

    def set_group_timer(self, group_id, time):
        return self.method(
            'editGroupInfo',
            {
                'group_guid': group_id,
                'slow_mode': int(time),
                'updated_parameters': ['slow_mode']
            }
        )['group']

    def set_group_admin(self, group_id, user_id, access = []):
        return self.method(
            'setGroupAdmin',
            {
                'group_guid': group_id,
                'member_guid': user_id,
                'access_list': access,
                'action': 'SetAdmin',
            }
        )['in_chat_member']

    def edit_group_info(self, chat_id, title = None, bio = None, show_chat_history = None):
        data = self.get_chat_info(chat_id)['group']
        return self.method(
            'editGroupInfo',
            {
                'group_guid': chat_id,
                'title': title or data.get('group_title', None),
                'description': bio or data.get('description', None),
                'chat_history_for_new_members': 'Visible' if show_chat_history else 'Hidden'if show_chat_history != None else data['chat_history_for_new_members'],
                'updated_parameters': ['title', 'description', 'chat_history_for_new_members']
            }
        )

    def delete_group_admin(self, group_id, user_id):
        return self.method(
            'setGroupAdmin',
            {
                'group_guid': group_id,
                'member_guid': user_id,
                'action': 'UnsetAdmin',
            }
        )['in_chat_member']

    def create_group(self, group_name, member_ids = []):
        return self.method(
            'addGroup',
            {
                'title': group_name,
                'member_guids': member_ids
            }
        )
    
    def join_group(self, group_link):
        return self.method('joinGroup', {'hash_link': group_link.split('/')[-1]})

    def leave_group(self, group_guid):
        return self.method('leaveGroup', {'group_guid': group_guid})

    def get_chat_join_link(self, chat_id):
        return self.method(f'get{tools.get_chat_type_by_id(chat_id)}Link', {f'{tools.get_chat_type_by_id(chat_id).lower()}_guid': chat_id})['join_link']

    def set_chat_link(self, chat_id):
        return self.method(f'set{tools.get_chat_type_by_id(chat_id)}Link', {f'{tools.get_chat_type_by_id(chat_id).lower()}_guid': chat_id})['join_link']

    def create_channel(self, channel_name, member_ids = [], channel_type = 'Public'):
        return self.method(
            'addChannel',
            {
                'channel_type': channel_type,
                'title': channel_name,
                'member_guids': member_ids
            }
        )

    def join_channel(self, channel_id):
        return self.method(
            'joinChannelAction',
            {
                'action': 'Join',
                'channel_guid': channel_id
            }
        )

    def join_channel_by_link(self, channel_link):
        return self.method('joinChannelByLink', {'hash_link': channel_link.split('/')[-1]})

    def leave_channel(self, channel_id):
        return self.method(
            'joinChannelAction',
            {
                'action': 'Leave',
                'channel_guid': channel_id
            }
        )

    def get_avatars(self, chat_id):
        return self.method('getAvatars', {'object_guid': chat_id})

    def upload_avatar(self, chat_id, file, thumbnai = None):
        main_id = self.file_upload(file)[0]['id']
        return self.method(
            'uploadAvatar',
            {
                'object_guid': chat_id,
                'thumbnail_file_id': self.file_upload(thumbnai)[0]['id'] if thumbnai != None else main_id,
                'main_file_id': main_id
            }
        )

    def delete_avatar(self, chat_id, avatar_id):
        return self.method(
            'deleteAvatar',
            {
                'object_guid': chat_id,
                'avatar_id': avatar_id
            }
        )

    def creat_voice_chat(self, chat_id):
        return self.method(
            f'create{tools.get_chat_type_by_id(chat_id)}VoiceChat',
            {f'{tools.get_chat_type_by_id(chat_id).lower()}_guid': chat_id}
        )

    def join_voice_chat(self, chat_id, voice_chat_id, self_id, sdp_offer_data = None):
        return self.method(
            f'join{tools.get_chat_type_by_id(chat_id)}VoiceChat',
            {
                'chat_guid': chat_id,
                'voice_chat_id': voice_chat_id,
                'self_object_guid': self_id,
                'sdp_offer_data': sdp_offer_data or '''v=0\r\no=- 7025254686977085379 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0\r\na=extmap-allow-mixed\r\na=msid-semantic: WMS LjIerKYwibTOvR0Ewwk1PBsYYxTInaoXObBE\r\nm=audio 9 UDP/TLS/RTP/SAVPF 111 63 103 104 9 0 8 106 105 13 110 112 113 126\r\nc=IN IP4 0.0.0.0\r\na=rtcp:9 IN IP4 0.0.0.0\r\na=ice-ufrag:6Hy7\r\na=ice-pwd:pyrxfUF+roBFRHDy6qgiKSAp\r\na=ice-options:trickle\r\na=fingerprint:sha-256 8C:90:E9:0C:E7:A4:79:7E:BF:78:81:ED:A7:19:82:64:71:F7:21:AB:43:4F:4B:3A:4C:EB:B5:3C:6A:01:CB:13\r\na=setup:actpass\r\na=mid:0\r\na=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level\r\na=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time\r\na=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01\r\na=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid\r\na=sendrecv\r\na=msid:LjIerKYwibTOvR0Ewwk1PBsYYxTInaoXObBE 00f6113c-f01a-447a-a72e-c989684b627a\r\na=rtcp-mux\r\na=rtpmap:111 opus/48000/2\r\na=rtcp-fb:111 transport-cc\r\na=fmtp:111 minptime=10;useinbandfec=1\r\na=rtpmap:63 red/48000/2\r\na=fmtp:63 111/111\r\na=rtpmap:103 ISAC/16000\r\na=rtpmap:104 ISAC/32000\r\na=rtpmap:9 G722/8000\r\na=rtpmap:0 PCMU/8000\r\na=rtpmap:8 PCMA/8000\r\na=rtpmap:106 CN/32000\r\na=rtpmap:105 CN/16000\r\na=rtpmap:13 CN/8000\r\na=rtpmap:110 telephone-event/48000\r\na=rtpmap:112 telephone-event/32000\r\na=rtpmap:113 telephone-event/16000\r\na=rtpmap:126 telephone-event/8000\r\na=ssrc:1614457217 cname:lYBnCNdQcW/DEUj9\r\na=ssrc:1614457217 msid:LjIerKYwibTOvR0Ewwk1PBsYYxTInaoXObBE 00f6113c-f01a-447a-a72e-c989684b627a\r\n''',
            }
        )

    def edit_voice_chat_setting(self, chat_id, voice_chat_id, custom_name):
        return self.method(
            f'set{tools.get_chat_type_by_id(chat_id)}VoiceChatSetting',
            {
                f'{tools.get_chat_type_by_id(chat_id).lower()}_guid': chat_id,
                'voice_chat_id': voice_chat_id,
                'title': custom_name ,
                'updated_parameters': ['title']
            }
        )

    def discard_voice_chat(self, chat_id, voice_chat_id):
        return self.method(
            f'discard{tools.get_chat_type_by_id(chat_id)}VoiceChat',
            {
                f'{tools.get_chat_type_by_id(chat_id).lower()}_guid': chat_id,
                'voice_chat_id': voice_chat_id
            }
        )

    def set_pin_chat(self, chat_id):
        return self.method(
            'setActionChat',
            {
                'object_guid': chat_id,
                'action': 'Pin'
            }
        )

    def set_unpin_chat(self, chat_id):
        return self.method(
            'setActionChat',
            {
                'object_guid': chat_id,
                'action': 'Unpin'
            }
        )

    def set_mute_chat(self, chat_id):
        return self.method(
            'setActionChat',
            {
                'object_guid': chat_id,
                'action': 'Mute'
            }
        )

    def set_unmute_chat(self, chat_id):
        return self.method(
            'setActionChat',
            {
                'object_guid': chat_id,
                'action': 'Unmute'
            }
        )

    def block_user(self, user_id):
        return self.method(
            'setBlockUser',
            {
                'user_guid': user_id,
                'action': 'Block'
            }
        )['chat_update']

    def unblock_user(self, user_id):
        return self.method(
            'setBlockUser',
            {
                'user_guid': user_id,
                'action': 'Unblock'
            }
        )['chat_update']

    def get_block_users(self):
        return self.method('getBlockUsers', {})

    def get_contacts(self):
        return self.method('getContacts', {})

    def get_contacts_updates(self, state):
        return self.method('getContactsUpdates', {'state': state})

    def get_contacts_last_online(self, chat_ids : list = None):
        return self.method('getContactsLastOnline', {'user_guds': chat_ids})

    def add_contact(self, phone_number, first_name, last_name):
        return self.method(
            'addAddressBook',
            {
                'phone': f'98{tools.parse_phone_number(phone_number)}',
                'first_name': first_name,
                'last_name': last_name
            }
        )

    def get_chat_folders(self):
        return self.method('getFolders', {})

    def get_suggested_folders(self):
        return self.method('getSuggestedFolders', {})

    def add_chat_folder(self, folder_name, exclude_chat_ids = [], exclude_chat_types = [], include_chat_ids = [], include_chat_types = [], add_to_top = True, folder_id = ''):
        data = dict(
            exclude_object_guids = exclude_chat_ids,
            include_object_guids = include_chat_ids,
            exclude_chat_types = exclude_chat_types,
            include_chat_types = include_chat_types,
            folder_id = folder_id, is_add_to_top = add_to_top,
            name = folder_name,
        )
        return self.make('addFolder', data)

    def get_privacy_setting(self):
        return self.method('getPrivacySetting', {})['privacy_setting']

    def get_my_sessions(self):
        return self.method('getMySessions', {})

    def get_two_passcode_status(self):
        return self.method('getTwoPasscodeStatus', {})['two_step_status']

    def check_two_step_passcode(self, password):
        if len(password) < 5:
            raise IndexError('Password vared shodeh bayad hadaghal 5 character bashad !')
        return self.method('checkTwoStepPasscode', {'password': password})['is_valid']

    def change_password(self, current_password, new_password, hint):
        return self.method(
            'changePassword',
            {
                'password': current_password,
                'new_password': new_password,
                'new_hint': hint
            }
        )

    def enable_two_step_verification(self, password, hint):
        return self.method(
            'setupTwoStepVerification',
            {
                'password': password,
                'hint': hint
            }
        )

    def disable_two_step_verification(self, current_password):
        return self.method('turnOffTwoStep', {'password': current_password})

    def request_recovery_email(self, current_password, email):
        return self.method(
            'requestRecoveryEmail',
            {
                'password': current_password,
                'recovery_email': email
            }
        )

    def verify_recovery_email(self, current_password, verification_code):
        return self.method(
            'verifyRecoveryEmail',
            {
                'password': current_password,
                'code': verification_code
            }            
        )

    def get_me(self):
        return post(
            json={
                'data': {},
                'method': 'getUser',
                'api_version': '2',
                'auth': self.auth,
                'client': {
                    'app_name': 'Mian',
                    'package': 'm.rubika.ir',
                    'app_version': '1.2.1',
                    'platform': 'PWA'
                }
            },
            url='https://messengerg2c1.iranlms.ir'
        ).json()['data']['user']

    def edit_profile(self, **kwargs):
        if 'username' in list(kwargs.keys()):
            return self.method(
                'updateUsername',
                {
                    'username': kwargs.get('username'),
                    'updated_parameters': ['username']
                }
            )['user']
        else:
            return self.method(
                'updateProfile',
                {
                    'first_name': kwargs.get('first_name'),
                    'last_name': kwargs.get('last_name'),
                    'bio': kwargs.get('bio'),
                    'updated_parameters': list(kwargs.keys())
                }
            )['user']

    def set_setting(self, show_my_last_online = False, show_my_phone_number = False, show_my_profile_photo = False, link_forward_message = False, can_join_chat = False):
        return self.method(
            'setSetting',
            {
                'settings': {
                    'show_my_last_online': 'Everybody' if show_my_last_online else 'Nobody',
                    'show_my_phone_number': 'Everybody' if show_my_phone_number else 'Nobody',
                    'show_my_profile_photo': 'Everybody' if show_my_profile_photo else 'Nobody',
                    'link_forward_message': 'Everybody' if link_forward_message else 'Nobody',
                    'can_join_chat_by': 'Everybody' if can_join_chat else 'Nobody'
                },
                'update_parameters': [
                    'Everybody' if show_my_last_online else 'Nobody',
                    'Everybody' if show_my_phone_number else 'Nobody',
                    'Everybody' if show_my_profile_photo else 'Nobody',
                    'Everybody' if link_forward_message else 'Nobody',
                    'Everybody' if can_join_chat else 'Nobody'
                ]
            }
        )

    def send_code(self, phone_number, send_internal = False):
        return self.method(
            'sendCode',
            {
                'phone_number': f'98{tools.parse_phone_number(phone_number)}',
                'send_type': 'Internal' if send_internal else 'SMS'
            }
        )

    def sing_in(self, phone_number, phone_code_hash, phone_code):
        return self.method(
            'signIn',
            {
                'phone_number': f'98{tools.parse_phone_number(phone_number)}',
                'phone_code_hash': phone_code_hash,
                'phone_code': phone_code
            }
        )

    def logout(self):
        return self.method('logout', {})

    def request_file(self, file):
        print(tools.get_mime_from_url(file))
        return self.method(
            'requestSendFile',
            {
                'file_name': file if not 'http' in file else f'pyrubi library {randint(1, 100)}',
                'mime': file.split('.')[-1] if not 'http' in file else tools.get_mime_from_url(file),
                'size': Path(file).stat().st_size if not 'http' in file else len(get(file).content)
            }
        )

    def file_upload(self, file):
        req = self.request_file(file)
        upload = maker(self.auth).upload
        bytef = open(file,'rb').read() if not 'http' in file else get(file).content
        url = req['upload_url']
        size = str(Path(file).stat().st_size) if not 'http' in file else str(len(get(file).content))
        header = {
            'auth': self.auth,
            'Host': req['upload_url'].replace('https://','').replace('/UploadFile.ashx',''),
            'chunk-size': size,
            'file-id': str(req['id']),
            'access-hash-send': req['access_hash_send'],
            'content-type': 'application/octet-stream',
            'content-length': size,
        }
        while True:
            try:
                if len(bytef) <= 131072:
                    header['part-number'], header['total-part'] = '1', '1'
                    j = upload(url=url, data=bytef, headers=header)
                    return [req, j['data']['access_hash_rec']]
                else:
                    t = len(bytef) // 131072 + 1
                    for i in range(1, t+1):
                        if i != t:
                            k = (i - 1) * 131072
                            header['chunk-size'], header['part-number'], header['total-part'] = '131072', str(i),str(t)
                            upload(url=url, data=bytef[k:k + 131072], headers=header)
                        else:
                            k = (i - 1) * 131072
                            header['chunk-size'], header['part-number'], header['total-part'] = str(len(bytef[k:])), str(i),str(t)
                            p = upload(url=url, data=bytef[k:], headers=header)
                    return [req, p['data']['access_hash_rec']]
            except:
                 continue