#!/usr/bin/python3
# https://fbchat.readthedocs.io/en/latest/examples.html

from fbchat import log, Client
from getpass import getpass
from fbchat.models import *
import useless
import usefull
import random
from auth_file import USERNAME, PASSWORD
from googletrans import Translator
import threading
from time import sleep
translator = Translator()


class Bot(Client):
    ahah_liste = ['ahah', 'mdr', 'lol', 'Mort de rire !', 'Trop marrant', 'xD', 'PTDR']
    what_liste = ['wat', 'What', 'Nani', 'keske', 'dafuk', 'da fuk']
    quizzes = {}
    shitpostbot = {}
    kicked = {}

    def onMessage(self, author_id, message_object, thread_id, thread_type, **kwargs):
        self.markAsDelivered(thread_id, message_object.uid)
        self.markAsRead(thread_id)

        log.info("{} from {} in {}".format(message_object, thread_id, thread_type.name))

        # pour éviter le spam... et oui j'ai fait cette erreur là.....
        if author_id != self.uid:
            to_send = self.tests(message_object.text, thread_id=thread_id, thread_type=thread_type, author_id=author_id, channel=self.fetchThreadInfo(thread_id)[thread_id].name)

            if to_send is not None:
                self.send(Message(to_send), thread_id=thread_id, thread_type=thread_type)
                sleep(2)

            self.trigger_double_mots(message_object.text, thread_id, thread_type)
            # self.shitpostbot5000()

    def shitpostbot5000(self):
        for chan in Bot.shitpostbot:
            if Bot.shitpostbot[chan][0].get_status():
                if Bot.shitpostbot[chan][0].get_latest():
                    print('Shitpostbot5000 a dégoté une nouvelle image...')
                    self.sendLocalImage(Bot.shitpostbot[chan][0].get_out(), thread_id=chan, thread_type=Bot.shitpostbot[chan][1])

    # TODO: move test in a standard module to use it with different bots
    def tests(self, texte, thread_id, thread_type, author_id, channel=''):

        if texte == '!help':
            help_text = 'Ce que je sais faire :\n\n' + \
                '!meteo <ville> ; <pays> ; <dans_n_heure(facultatif)>\n' + \
                '!wikipedia <truc_a_chercher>\n' + \
                '!useless \n' + \
                '!chuck \n' + \
                '!nordpress \n '\
                '!quizz [start|new|reset|scoreboard|indice|round|question] \n' + \
                '!q <reponse> pour répondre au quizz\n' + \
                '!haddock \n' + \
                '!philo \n' + \
                '!pipo\n' + \
                '!rename <personne> ; <pseudo> \n' + \
                '!remove <personne> ; <raison(facultatif)> \n' + \
                '!reinvite <personne(facultatif)>\n' + \
                '!kohlanta <nom>\n' + \
                '!rateau \n' + \
                '!maps <nom_du_lieu> <destination(facultatif)> ... not yet fully fonctionnal\n' + \
                '!memes <image_name_or_url> ; <texte1> ; <texte2(facultatif)>\n' + \
                '!ping \n' + \
                '!translate <phrase> ; <lang_source> ; <lang_dest>\n' + \
                '!shitpostbot5000 [status|on|off|random <keyword(facultatif)>] ... ne pas utiliser PLEASE\n' + \
                '!title <newtitle>\n'\
                '!userlist\n'\
                '!about -> vas-y test-moi !\n'
            return random.choice('Hummmm non j\'ai la flemme là', help_text)
        elif '!translate' in texte:
            texte = texte.replace('!translate ', '').split(' ; ')
            try:
                return translator.translate(text=texte[0], dest=texte[2], src=texte[1]).text
            except Exception as e:
                print(e)
                return 'Tiens j\'y arrive pas, Apparement, ça ne marche pas comme ça.'
        elif texte == '!useless':
            return useless.useless()
        elif texte == '!nordpress':
            return useless.nordpresse()
        elif texte == '!chuck':
            return useless.chuck()
        elif texte == '!philo':
            return useless.genererSujet()
        elif texte == '!haddock':
            return useless.haddock()

        elif '!title ' in texte:
            texte = texte.replace("!title ", '')
            client.changeThreadTitle(texte, thread_id=thread_id, thread_type=thread_type)

        # renomer qqn
        # FIXME: make rename command work
        elif '!rename' in texte:
            texte = texte.replace('!rename ', '').split(' ; ')
            for user in self.fetchAllUsersFromThreads([self.fetchThreadInfo(thread_id)[thread_id]]):
                if user.name == texte[0]:
                    self.changeNickname(nickname=texte[1], user_id=user.uid, thread_id=thread_id, thread_type=thread_type)
                    return None
                else:
                    return random.choice(['T\'es sur de ton coup là ?', 'chais pas qui c\'est...'])

        # TODO: test remove
        # kick qqn d'un groupe
        elif '!remove ' in texte and thread_type == ThreadType.GROUP:
            texte = texte.replace('!remove ', '').split(' ; ')
            user_to_remove = None
            for user in self.fetchAllUsersFromThreads([self.fetchThreadInfo(thread_id)[thread_id]]):
                if user.name == texte[0]:
                    user_to_remove = user
                if user.uid == author_id:
                    author_name = user.name
            if user_to_remove is not None:
                log.info("{} will be removed from {} by {}".format(user_to_remove.uid, thread_id, author_id))
                try:
                    self.removeUserFromGroup(user_to_remove.uid, thread_id=thread_id)
                except:
                    return "J'ai pas le droit de faire ça moi"
                if thread_id in Bot.kicked:
                    Bot.kicked[thread_id].append(user_to_remove)
                else:
                    Bot.kicked[thread_id] = [user_to_remove]
                return '{} a été kick du groupe par {} {}'.format(texte[0], author_name, 'pour la raison : {}'.format(texte[1]) if len(texte) == 2 else '')
            else:
                return random.choice(['T\'es sur de ton coup là ?', 'chais pas qui c\'est...'])

        elif texte == '!userlist' and thread_type == Thread.GROUP:
            return ", ".join([user.name for user in self.fetchAllUsersFromThreads([self.fetchThreadInfo(thread_id)[thread_id]])])

        # réinviter le dernier mec kické du group
        # TODO: test reinvite
        elif texte == '!reinvite' and thread_type == Thread.GROUP:
            if 'thread_id' in Bot.kicked:
                self.addUsersToGroup(Bot.kicked[thread_id][-1].uid, thread_id=thread_id)
        elif '!reinvite ' in texte:
            if 'thread_id' in Bot.kicked:
                finded = False
                for user in Bot.kicked[thread_id]:
                    if user.name == texte.replace('!reinvite ', ''):
                        finded = True
                        self.addUsersToGroup(user.uid, thread_id=thread_id)
                        indice = Bot.kicked[thread_id].index(user)
                if finded:
                    # faut supprimer l'utilisateur réinvité de la liste des gens kickés
                    del Bot.kicked[thread_id][indice]
                    if len(Bot.kicked[thread_id]) == 0:
                        # on supprime le groupe de la liste des groupes où des gens ont étés kickés
                        del Bot.kicked[thread_id]

                else:
                    return 'Mec je l\'ai pas encore kick, mais tu peux reinviter ces gens là :\n' + "\n".join([user.name for user in Bot.kicked[thread_id]])
            else:
                return 'T\'es débile ou quoi ? Je peux pas réinviter des gens que je n\'ai pas kické moi même en fait... \n\n\n Hummmm par contre je pourais éventuellement inviter des random mec...ou meuf...'

        # SHitpostbot5000
        # TODO: shitpostbot5000 random auto with timer
        elif texte == '!shitpostbot5000 on':
            if thread_id not in Bot.shitpostbot:
                Bot.shitpostbot[thread_id] = [useless.Shitpostbot5000(), thread_type]
            Bot.shitpostbot[thread_id][0].set_on()
        elif texte == '!shitpostbot5000 status':
            if thread_id not in Bot.shitpostbot:
                return 'Ce truc n\'est pas activé et doit, à mon avis rester éteint...'
            else:
                return 'Eh oui, c\'est trop tard, le démon est déjà à l\'oeuvre' if Bot.shitpostbot[thread_id][0].get_status() else 'Le diable se repose...'
        elif texte == '!shitpostbot5000 off':
            if thread_id in Bot.shitpostbot:
                Bot.shitpostbot[thread_id][0].set_off()
        elif '!shitpostbot5000 random' in texte:
            texte = texte.replace('!shitpostbot5000 random', '')
            if texte == '':
                self.sendLocalImage(useless.Shitpostbot5000.random(), thread_id=thread_id, thread_type=thread_type)
            else:
                self.sendLocalImage(useless.Shitpostbot5000.random(texte), thread_id=thread_id, thread_type=thread_type)

        # générateur de memes
        elif texte == '!memes templates':
            return useless.Memes.get_templates()
        elif texte == '!memes help':
            return useless.Memes.get_help()

        elif '!memes ' in texte:
            texte = texte.replace('!memes ', '').split(' ; ')
            if len(texte) == 3:
                image, text1, text2 = texte
            elif len(texte) == 2:
                image, text1 = texte
                text2 = ''
            try:
                meme = useless.Memes(image, text1, text2)
                meme.process()
                self.sendLocalImage(meme.get_result(), thread_id=thread_id, thread_type=thread_type)
                sleep(2)
            except:
                return 'Ya un problème dans la plantation...'

        elif any(word.lower() in texte.lower() for word in ["let\'s go", "c'est parti", "go ", "allons "]):
            return 'é zé bardi !'
        elif any(word.lower() in texte.lower().split(' ') for word in ['noice', 'nice']):
            self.sendEmoji(emoji="👍", size=EmojiSize.LARGE, thread_id=thread_id, thread_type=thread_type)
            # self.send(Message(emoji_size=EmojiSize.LARGE), thread_id=thread_id, thread_type=thread_type)
        elif '!kohlanta' in texte:
            texte = texte.replace('!kohlanta ', '')
            return useless.kohlanta(texte, channel)
        elif texte == '!pipo':
            return useless.pipo('useless/pipotron.txt')
        elif texte == '!ping':
            return 'Pong !'
        elif texte == '!rateau':
            return useless.getRateau()

        # petit jeu de quizz
        elif '!quizz' in texte:
            if 'start' in texte:
                if thread_id not in Bot.quizzes.keys():
                    Bot.quizzes[thread_id] = useless.Quizz()
                return Bot.quizzes[thread_id].start()
            elif thread_id not in Bot.quizzes.keys():
                return 'Perdu ! T\'as oublié de lancer une game looser'
            if 'new' in texte:
                return Bot.quizzes[thread_id].new()
            if 'scoreboard' in texte:
                if texte.replace('!quizz scoreboard ', '') != '':
                    return Bot.quizzes[thread_id].scoreboard(texte.replace('!quizz scoreboard ', ''))
                else:
                    return Bot.quizzes[thread_id].scoreboard()
            if 'reset' in texte:
                return Bot.quizzes[thread_id].reset()
            if 'indice' in texte:
                return Bot.quizzes[thread_id].indice()
            if 'round' in texte:
                return Bot.quizzes[thread_id].get_round()
            if 'question' in texte:
                return Bot.quizzes[thread_id].get_question()
        elif '!q ' in texte and thread_id in Bot.quizzes.keys():
            personne = self.fetchUserInfo(author_id)[author_id].name
            print(personne)
            return Bot.quizzes[thread_id].answer(texte.replace('!q ', ''), personne)
        elif "!indice" in texte and thread_id in Bot.quizzes.keys():
            return Bot.quizzes[thread_id].indice()
        elif "!scoreboard" in texte and thread_id in Bot.quizzes.keys():
            return Bot.quizzes[thread_id].scoreboard()

        # meteo
        elif '!meteo' in texte:
            try:
                texte = texte.replace('!meteo ', '').split(' ; ')
                if len(texte) == 2:
                    return usefull.meteo_de(texte[0], texte[1])
                else:
                    return usefull.meteo_de(texte[0], texte[1], dans_n_heures=int(texte[2]))
            except:
                return 'Ousp, c\'est cassé...'

        # wikipédia
        elif '!wikipedia' in texte:
            try:
                texte = texte.replace('!wikipedia ', '')
                return usefull.wiki(texte)
            except:
                return 'Ousp, j\'ai glissé chef...'
        elif '!maps' in texte:
            try:
                return usefull.maps(texte.replace('!maps ', ''))
            except:
                return 'Houston, on a un problème...'
        elif texte == '!about' or texte == '!cyborg':
            return 'Hello, je suis A.N.U.B.I.S. A Not Usefull But Intelligent System, petit frère de nardco créé par le talentueux LawiK aka Wikle aka Cyborg aka Loïc Dub que je vénère !'

        # les triggers en tout genre
        elif 'Ah' in texte:
            self.sendLocalImage('images/ah.png', thread_id=thread_id, thread_type=thread_type)
            sleep(2)
        elif any(word.lower() in texte.lower() for word in Bot.ahah_liste):
            return random.choice(Bot.ahah_liste)
        elif any(word.lower() in texte.lower() for word in Bot.what_liste):
            return random.choice(Bot.what_liste) + '?!'

        # doit rester à la fin des elif
        elif '!' in texte and not any(word in texte for word in [' ! ', '! ', ' !']):
            return 'Gné ?'

        return None

    def trigger_double_mots(self, texte, thread_id, thread_type):
        # genre coucou coucou donnera : Oh, coucoucou c'est marrant ça... et faire faire donnera faifaire
        texte = texte.split(' ')
        indice = len(texte)
        voyelles = ['a', 'e', 'i', 'o', 'u', 'y']
        for i in range(len(texte) - 1):
            if texte[i] == texte[i + 1]:
                for v in voyelles:
                    if texte[i].find(v) != -1:
                        indice = min(texte[i].find(v), indice)
                if texte[i][indice] in voyelles:
                    indice += 1
                mot = texte[i][:indice + 1] + texte[i]
                self.sendMessage(message="Oh, {} c'est marrant ça...".format(mot), thread_id=thread_id, thread_type=thread_type)
                return None


if __name__ == '__main__':

    # username = str(input("Username: "))
    # client = Bot(username, getpass())
    client = Bot(USERNAME, PASSWORD)
    # Bot.shitpostbot['1627890897259691'] = [useless.Shitpostbot5000(), ThreadType.GROUP]
    # Bot.shitpostbot['1627890897259691'][0].set_on()
    client.listen()