import sys
import random
import datetime
import time
import threading

import discord
import sqlite3

import interface

secrets_file = open(sys.argv[1], mode="rt")
secrets = secrets_file.read()
secrets_file.close()

token = secrets

intents = discord.Intents.default()
intents.message_content = True
intents.members = True
intents.moderation = True

client = discord.Client(intents=intents, activity=discord.Game(name='En train de niquer des mères'))

interface.client = client

import forgejo

database = sqlite3.connect(sys.argv[2])
cursor = database.cursor()

#try:
#  cursor.execute("CREATE TABLE casino (id INT PRIMARY KEY, cash INT)")
#  database.commit()
#except:
#  print("La table existe déja")

guilds = []

globals()["gmembers"] = {}

async def pinguncon(message):
  #fcalva's server
  if message.guild.id == 750665878072328242:
    await message.channel.send("<@499533339468759052>")
  elif message.guild.id in [1008485562304450610, 1157767629738618941]:
    await message.channel.send("<@755081785393676328>")
  elif message.guild.id == 1294017120631525416:
    await message.channel.send("<@504751919760408617>")
  else:
    await message.channel.send("Pas dispo ici")

async def pingjuif(message):
    if message.guild.id in [1008485562304450610, 1157767629738618941]:
      await message.channel.send("<@459021187083927553>")
    else:
      message.channel.send("Pas dispo ici")

async def pingrand(message):
  choice = random.choice(globals()["gmembers"][str(message.guild.id)])
  await message.channel.send("<@"+str(choice.id)+">")

async def reload(message):
  cursor.execute(f"CREATE TABLE IF NOT EXISTS roulette (gid INT PRIMARY KEY, shots INT)")
  gid = int(message.guild.id)
  ret = cursor.execute(f"SELECT shots FROM roulette WHERE gid = {gid}").fetchone()
  shots = random.randint(0,5)
  if ret == None:
    cursor.execute(f"INSERT INTO roulette (gid,shots) VALUES ({gid},{shots})")
  else:
    cursor.execute(f"UPDATE roulette SET shots = {shots} WHERE gid = {gid}")
  database.commit() 
  await message.channel.send("Revolver rechargé")
  

async def roulette(message):
  cursor.execute(f"CREATE TABLE IF NOT EXISTS roulette (gid INT PRIMARY KEY, shots INT)")
  database.commit() 
  gid = int(message.guild.id)
  ret = cursor.execute(f"SELECT shots FROM roulette WHERE gid = {gid}").fetchone()
  if ret == None:
    shots = random.randint(0,5)
    cursor.execute(f"INSERT INTO roulette (gid,shots) VALUES ({gid},{shots})")
    database.commit()
  else:
    shots = ret[0]
  print("Shots : ", shots)
  if shots <= 0:
    tdelt = datetime.timedelta(minutes=5)
    uid = message.author.id
    try:
      await message.author.timeout(tdelt, reason="Vous avez perdu à la roulette...")
      await message.channel.send(f"<@{uid}> s'est tiré une balle, et est dans un coma pendant 5 minutes")
    except Exception as err:
      await message.channel.send("Une erreur s'est produite :  `" + str(err) + "`")
    nshots = random.randint(0,5)
    cursor.execute(f"UPDATE roulette SET shots = {nshots} WHERE gid = {gid}")
    database.commit()
  else:
    shots -= 1
    cursor.execute(f"UPDATE roulette SET shots = {shots} WHERE gid = {gid}")
    database.commit()
    await message.channel.send("Clic... il n'y avait pas de cartouche dans la chambre...")

async def casino_init(message):
  usrid = int(message.author.id)
  gid = int(message.guild.id)
  try:
    cursor.execute(f"CREATE TABLE IF NOT EXISTS tab_{gid} (id INT PRIMARY KEY, cash INT, lst_coll INT)")
    cursor.execute(f"INSERT INTO tab_{gid} (id, cash, lst_coll) VALUES ({usrid}, 0, 0)")
    database.commit()
    await message.channel.send(f"Casino initialisé pour <@{usrid}>")
  except:
    await message.channel.send(f"Échec ! Réessayez plus tard")

init_global_str = "Essayer d'initialiser le casino du serveur avec ?init"
init_perso_str = "Essayez d'initialiser votre portemonnaie avec ?init"

async def balance(message):
  usrid = int(message.author.id)
  gid = int(message.guild.id)
  try:
    cash = cursor.execute(f"SELECT cash FROM tab_{gid} WHERE id={usrid}").fetchone()
  except:
    await message.channel.send(init_global_str)
  if cash != None:
    await message.channel.send(f"Vous avez {cash[0]}$")
  else:
    await message.channel.send(init_perso_str)

async def collect(message):
  collect_gain = 50
  cooldown = 10
  curr_time = int(time.time())
  usrid = int(message.author.id)
  gid = int(message.guild.id)
  lst_coll = 0
  try:
    lst_coll = cursor.execute(f"SELECT lst_coll FROM tab_{gid} WHERE id={usrid}").fetchone()[0]
  except:
    await message.channel.send(init_perso_str)
    return
  if lst_coll >= curr_time - cooldown:
    rtime = (-curr_time + cooldown + lst_coll)
    await message.channel.send(f"Vous pourrez toucher votre RSA dans {rtime} minutes")
    return
  cash = None
  cash = cursor.execute(f"SELECT cash FROM tab_{gid} WHERE id={usrid}").fetchone()
  if cash != None:
    cash = cash[0]
    cash += collect_gain
    cursor.execute(f"UPDATE tab_{gid} SET lst_coll = {curr_time} WHERE id={usrid}")
    cursor.execute(f"UPDATE tab_{gid} SET cash = {cash} WHERE id={usrid}")
    database.commit()
    await message.channel.send(f"Vous avez recu {collect_gain}$ en RSA. Vous avez désormais {cash}$\n"\
                               f"Revenez dans {cooldown} minutes pour votre prochain chèque")
  else:
    await message.channel.send(init_perso_str)
 
async def slot(message):
  amnt = message.content.split(' ')[1]
  try:
    amnt = int(amnt)
  except:
    await message.channel.send("Quantité invalide")
    return
  gid = int(message.guild.id)
  uid = int(message.author.id)
  ret = cursor.execute(f"SELECT cash FROM tab_{gid} WHERE id={uid}").fetchone()
  if ret == None:
    await message.channel.send(init_perso_str)
    return
  cash = ret[0]
  if amnt > cash:
    await message.channel.send("Vous n'avez pas assez d'argent")
    return
  roll = random.random()
  gain = 0
  print("Roll :",roll)
  if roll < 1/6:
    await message.channel.send(f"<@{uid}> a perdu toute sa mise")
  if roll >= 1/6 and roll < 3/6:
    gain = int(amnt*0.35*random.random())
    await message.channel.send(f"<@{uid}> n'a remporté que {gain}$")
  if roll >= 3/6 and roll < 5/6:
    gain = int(amnt*1.1*random.random())
    await message.channel.send(f"<@{uid}> a réussi à remporter {gain}$")
  if roll >= 5/6 and roll < 19/20:
    gain = int(amnt*0.4 + amnt*1.2*random.random())
    await message.channel.send(f"<@{uid}> a extrait {gain}$ des griffes de la machine")
  if roll >= 19/20:
    gain = int(amnt*4 + amnt*16*random.random())
    await message.channel.send(f"## <@{uid}> JACKPOT ! Vous avez gagné {gain}$ !")
  cash -= amnt-gain
  cursor.execute(f"UPDATE tab_{gid} SET cash = {cash} WHERE id={uid}") 
  database.commit()

async def leaderboard(message):
  uid = int(message.author.id)
  gid = int(message.guild.id)
  lb = None
  result = cursor.execute(f"SELECT * FROM tab_{gid} ORDER BY cash DESC").fetchall()
  msgstr = "## ===== Leaderboard =====\n"
  i = 0
  rlen = len(result)
  while i < 10 and i < rlen:
    uid = result[i][0]
    ucash = result[i][1]
    msgstr += " "+str(i+1)+f". <@{uid}> - {ucash}$\n"  
    i += 1
  await message.channel.send(msgstr, allowed_mentions=discord.AllowedMentions().none())

async def ecoaide(message):
  await message.channel.send("Eco+, un bot Eco plus pour faire des conneries\n"\
                              "?pinguncon : Ping le con local\n"\
                              "?pingunjuif : Ping le juif local\n"\
                              "?pingrand : Ping un membre aléatoire du serveur\n"\
                              "?roulette : Jouez à la roulette russe\n"\
                              "?reload : Réinitialisez la roulette russe\n")

async def ecohelp(message):
  await message.channel.send("Eco+ help page \n"\
                             "?pinguncon : Ping the local dumbass\n"\
                             "?pingrand : Ping a random user\n"\
                             "?roulette : Take one shot on six to get timed out")

async def hello(message):
  await message.channel.send('henlo')

commentaires_zizi = [
  #0
  ["Vous avez essayé de mesurer à la base ?","Dur d'avoir des chromosomes XX. Retourne à la cuisine"],\
  #1
  ["J'ai pitié.", "Échec critique !"],\
  #2
  ["Tu peux toujours te dire que la taille ne compte pas"],\
  #3
  ["Dire que c'était ma taille à trois ans..."],\
  #4
  ["Retourne dans ton 4x4 micropénis"],\
  #5
  ["En impérial, ça aurait été la moyenne"],\
  #6
  ["T'es pas la bite la plus dure du gloryhole"],\
  #7
  [""],\
  #8
  [""],\
  #9
  [""],\
  #10
  [""],\
  #11
  [""],\
  #12
  [""],\
  #13
  ["La moyenne, pour de vrai"],\
  #14
  [""],\
  #15
  [""],\
  #16
  ["La verité est dure à avaler"],\
  #17
  ["C'est roc, c'est un pic, c'est un cap. Que dis-je ? C'est une péninsule"],\
  #18
  ["Si le goût se rapporte à la taille, vous êtes le phoenix des hôtes du gang bang"],\
  #19
  ["Bien membré !"],\
  #20
  ["Je veux la même !", "Coup critique !"],\
  #21
  ["Profite de tes chromosomes YY :moai:", "La taille moyenne en Uganda"]
]

async def zizi(message):
  id = message.author.id
  size = random.randint(0,10) + random.randint(0,11)
  comment = random.choice(commentaires_zizi[size])
  await message.channel.send(f"<@{id}>, votre chibre fait **{size} cm**. {comment}")

@client.event
async def on_ready():
  print(f'We have logged in as {client.user}')
  async for guild in client.fetch_guilds(limit=150):
    print(str(guild.id)+":")
    guilds.append(guild)
    sid = str(guild.id)
    globals()["gmembers"] |= {sid:[]}
    async for member in guild.fetch_members(limit=150):
      globals()["gmembers"][sid].append(member)
      print("  "+str(member))

cmd_dict = {\
  "?hello":hello,\
  "?pinguncon":pinguncon,\
  "?pingrand":pingrand,\
  "?pingunjuif":pingjuif,\
  "?zizi":zizi,\
  "?roulette":roulette,\
  "?help":ecohelp,\
  "?aide":ecoaide,\
  "?init":casino_init,\
  "?cash":balance,\
  "?collect":collect,\
  "?lb":leaderboard,\
  "?reload":reload,\
  "?slot":slot,\
}

@client.event
async def on_message(message):
  if message.author == client.user:
    return

  content = message.content.split(" ")[0]

  if not content:
    return
  if content[0] != "?":
    return
  if not content in cmd_dict:
    await message.channel.send("Commande non reconnue !")
    return

  try:
    await cmd_dict[content](message)
  except Exception as err:
    print(err)
    await message.channel.send("Une erreur s'est produite :  `" + str(err) + "`")

def do_forgejo_thread():
  forgejo.app.run(port=5000)

forgejo_thread = threading.Thread()
forgejo_thread.run = do_forgejo_thread 

print("227")
forgejo_thread.start()
client.run(token)