import json
import string
import discord

class StarWarsChar():
  def __init__(self, bot):
    self.bot = bot

  def get_char_name(self, user : str):
    self.bot.log("Getting name for "+self.bot.database_funcs.get_name(user)+"'s character")
    user_character = self.bot.database["starwars characters"].find_one({"_id":user})

    if user_character != None:
      self.bot.log("Name is "+user_character["Name"])
      return user_character["Name"]
    else:
      self.bot.log("Just using "+self.bot.database_funcs.get_name(user))
      return self.bot.database_funcs.get_name(user)

  def set_up_dict(self, cmd : dict):
    self.bot.log("Setting up a dictionary in a nice way")
    if bool(cmd):
      keys = list(cmd)
      values = list(cmd.values())
      result = ""
      if isinstance(values[0],dict):
        return ", ".join(values)
      else:
        for i, key in enumerate(keys):
          if type(key) is list:
            if i%3 != 2:
              result += "**" + key + "**" + ": " + ", ".join(values[i]) + " "
            else:
              result += "**" + key + "**" + ": " + ", ".join(values[i]) + "\n"
          else:
            if i%3 != 2:
              result += "**" + key + "**" + ": " + str(values[i]) + " "
            else:
              result += "**" + key + "**" + ": " + str(values[i]) + "\n"
        self.bot.log("Returning a dictionary, but well formatted")
        return result
    else:
      self.bot.log("Couldn't find anything")
      return "There doesn't seem to be anything here..."

  def look_up(self, data : dict, key : str, cmd : str = ""):
    if cmd == " ":
      cmd = ""
    elif cmd != "":
      while cmd[0] == " ":
        cmd = cmd[1:]
        if cmd == "":
          break

    self.bot.log("Looking up "+key)
    if key in data:
      self.bot.log(key+" exists")
      if cmd == "":
        if type(data[key]) is dict and key != "Weapons":
          return self.set_up_dict(data[key])
        elif key == "Weapons":
          self.bot.log("Does this even get used? I'm too scared to delete it")
          if bool(data[key]):
            self.bot.log("Found "+(", ".join(list(data[key]))))
            return ", ".join(list(data[key]))
          else:
            self.bot.log("There is nothing here")
            return "There doesn't seem to be anything here..."
        else:
          if str(data[key]) != "":
            self.bot.log("Returning "+str(data[key]))
            return data[key]
          else:
            self.bot.log("There was nothing there")
            return "There doesn't seem to be anything here"
      elif cmd[0] == '+':
        self.bot.log("Trying to add to "+key)
        try:
          cmd = cmd[1:]
          while cmd[0] == ' ':
            cmd = cmd[1:]
        except:
          self.bot.log("Yeah, that fucked up")
          return "Can't do that"

        if type(data[key]) is int:
          try:
            new_value = data[key] + int(cmd)
            data[key] = new_value
            self.bot.log("Added "+cmd+" to "+key)
            return data
          except:
            self.bot.log("Couldn't add "+cmd+" to "+key)
            return "Can't add that"
        elif type(data[key]) is list:
          try:
            data[key].append(cmd)
            self.bot.log("Added "+cmd+" to "+key)
            return data
          except:
            self.bot.log("Couldn't add "+cmd+" to "+key)
            return "Can't add that"
        else:
          self.bot.log("Yeah, I can't add that to "+key)
          return "Can't add that"

      elif cmd[0] == '-':
        self.bot.log("Trying to remove/subtract from "+key)
        try:
          cmd = cmd[1:]
          while cmd[0] == ' ':
            cmd = cmd[1:]
        except:
          self.bot.log("Yeah, that fucked up")
          return "Can't do that"

        if type(data[key]) is int:
          try:
            new_value = data[key] - int(cmd)
            data[key] = new_value
            self.bot.log("Subtracted "+cmd+" from "+key)
            return data
          except:
            self.bot.log("Couldn't subtract "+cmd+" from "+key)
            return "Can't remove that"
        elif type(data[key]) is list:
          try:
            data[key].remove(cmd)
            self.bot.log("Removed "+cmd+" from "+key)
            return data
          except:
            self.bot.log("Couldn't remove "+cmd+" from "+key)
            return "Can't remove that"
        else:
          self.bot.log("Yeah, I can't remove/subtract that from "+key)
          return "Can't remove that"
      else:
        while cmd[0] == ' ':
          cmd = cmd[1:]

        if type(data[key]) is dict:
          new_key = cmd.split(" ")[0]
          cmd = cmd[len(new_key):]
          if cmd != "":
            while cmd[0] == " ":
              cmd = cmd[1:]
              if cmd == "":
                break
          self.bot.log("Looking up "+new_key+" in "+key)
          look_up_result = self.look_up(data[key],new_key,cmd)
          if type(look_up_result) is dict:
            data[key] = look_up_result
            return data
          else:
            return look_up_result
        elif type(data[key]) != list:
          self.bot.log("Trying to change "+key+" to "+cmd)
          try:
            cmd = type(data[key])(cmd)
            data[key] = cmd
            self.bot.log("Did that")
            return data
          except:
            self.bot.log("No. That did not work")
            return "Wrong data type"
        else:
          self.bot.log("Yeah, that didn't work")
          return "Wrong data type"
    else:
      self.bot.log("Couldn't find "+key)
      self.bot.log("Testing to see if it's a multi-word key")
      cmd = key + " " + cmd
      words = cmd.split(" ")
      search = ""
      i = 0
      while search not in data:
        try:
          search += " " + words[i]
          i += 1
        except:
          self.bot.log("It wasn't. "+search+" doesn't exist")
          return search + " doesn't exist"
        if search[0] == " ":
          search = search[1:]
      self.bot.log("Yeah! Did that! The key was "+search)

      cmd = cmd[len(search):]
      if cmd != "":
        while cmd[0] == " ":
          cmd = cmd[1:]
          if cmd == "":
            break

      if cmd == "":
        self.bot.log("Returning "+search)
        return self.set_up_dict(data[search])
      else:
        new_key = cmd.split(" ")[0]
        cmd = cmd[len(new_key):]
        if cmd != "":
          while cmd[0] == " ":
            cmd = cmd[1:]
            if cmd == "":
              break
        look_up_result = self.look_up(data[search],new_key,cmd)
        if type(look_up_result) is dict:
          data[search] = look_up_result
          return data
        else:
          return look_up_result

  def character_sheet(self,character : dict):
    self.bot.log("Setting up a character sheet for "+character["Name"])
    divider = "--------------------\n"
    name = character["Name"]
    textf = ""
    if character["Force-rating"] != 0:
      textf = "\n**Force Rating**: "+str(character["Force-rating"])

    text1 = "**Species**: "+character["Species"]+"\n**Career**: "+character["Career"]+"\n**Specialization Trees**: "+", ".join(character["Specialization-trees"])+textf+"\n**Soak**: "+str(character["Soak"])
    text2 = "\n\n**Wounds**: "+str(character["Wounds"])+"/"+str(character["Wound-threshold"])+"\n**Strain**: "+str(character["Strain"])+"/"+str(character["Strain-threshold"])
    text3 = self.set_up_dict(character["Characteristics"])
    text4 = self.set_up_dict(character["Skills"])
    text5 = ""
    text6 = ""
    text7 = ""
    text8 = ""

    if bool(character["Talents"]):
      text5 = "**Talents**: "+", ".join(list(character["Talents"]))+"\n\n"

    if bool(character["Force-powers"]):
      text6 = "**Force Powers**: "+", ".join(list(character["Force-powers"]))+"\n\n"

    text7 = "**Equipment**: "+", ".join(character["Equipment"])+"\n**Credits**: "+str(character["Credits"])+"\n**Weapons**: "+", ".join(list(character["Weapons"]))+"\n"+divider

    if bool(character["Obligations"]):
      text8 = "**Obligations**: "+",".join(list(character["Obligations"]))

    return name, text1+text2+"\n\n"+text3+divider+text4+"\n"+divider+text5+text6+text7+text8

  def char_data(self,user : str,cmd : str):
    user_character = self.bot.database["starwars characters"].find_one({"_id":user})

    key = string.capwords(cmd.split(" ")[0])
    cmd = cmd[len(key):]
    if cmd == " ":
      cmd = ""
    elif cmd != "":
      while cmd[0] == " ":
        cmd = cmd[1:]
        if cmd == "":
          break

    self.bot.log("Looking for "+self.bot.database_funcs.get_name(user)+"'s character")
    if user_character != None:
      self.bot.log("Found it! Looking for "+key+" in the data")
      if key in user_character:
        self.bot.log("Found it!")
        if type(user_character[key]) is dict:
          self.bot.log("It's a dictionary!")
          if cmd == "":
            self.bot.log("Retrieving data")
            if key == "Weapons":
              if bool(user_character[key]):
                self.bot.log("Returning a list of weapons")
                return ", ".join(list(user_character[key]))
              else:
                self.bot.log("The character doesn't have any weapons. Which is probably for the best. Like, who just walks around with weapons?")
                return "There doesn't seem to be anything there..."
            else:
              return self.set_up_dict(user_character[key])
          elif cmd[0] == "+":
            self.bot.log("Gonna add something!!!")
            try:
              cmd = cmd[1:]
              while cmd[0] == ' ':
                cmd = cmd[1:]
            except:
              self.bot.log("Nope. That didn't happen")
              return "Can't do that"

            if (key == "Talents" or key == "Force-powers") and "," in cmd:
              cmd = cmd.split(",")
              while cmd[1][0] == " ":
                cmd[1] = cmd[1][1:]
              self.bot.log("Adding "+cmd[0]+" to "+key)
              self.bot.database["starwars characters"].update_one({"_id":user},
                {"$set": {key+"."+cmd[0] : cmd[1]}})
              return cmd[0]+" added to "+key+" for " + user_character["Name"]

            elif key == "Obligations" and "," in cmd:
              cmd = cmd.split(",")
              while cmd[1][0] == " ":
                cmd[1] = cmd[1][1:]
              self.bot.log("Adding "+cmd[0]+" to "+key)
              try:
                self.bot.database["starwars characters"].update_one({"_id":user},
                  {"$set": {key+"."+cmd[0] : int(cmd[1])}})
              except:
                self.bot.log("Fucked that up")
                return "Wrong data type"
              return cmd[0]+" added to "+key+" for " + user_character["Name"]

            elif key == "Weapons":
              with open("gwendolyn/resources/star_wars/starwarstemplates.json", "r") as file_pointer:
                templates = json.load(file_pointer)
              new_weapon = templates["Weapon"]
              self.bot.log("Adding "+cmd+" to "+key)
              self.bot.database["starwars characters"].update_one({"_id":user},
                {"$set": {key+"."+cmd : new_weapon}})

              return cmd+" added to weapons for " + user_character["Name"]

            else:
              self.bot.log("That's not happening")
              return "Can't add that"

          elif cmd[0] == "-":
            self.bot.log("Gonna subtract/remove something")
            try:
              cmd = cmd[1:]
              while cmd[0] == ' ':
                cmd = cmd[1:]
            except:
              self.bot.log("AAAAAAAAAAAA ")
              return "Can't do that "

            if key == "Talents" or key == "Force-powers" or key == "Weapons" or key == "Obligations":
              self.bot.log("Trying to remove "+cmd+" from "+key)
              if cmd in user_character[key]:
                self.bot.database["starwars characters"].update_one({"_id":user},
                  {"$unset": {cmd}})
                self.bot.log("I did that")
                return cmd+" removed from "+key+" from "+user_character["Name"]
              else:
                self.bot.log("Welp. I fucked that up")
                return "Can't remove that"
            else:
              self.bot.log("Urgh!")
              return "Can't remove that"

          else:
            self.bot.log("Looking up "+cmd+" in "+key)
            if key == "Talents" or key == "Force-powers":
              new_key = cmd
              new_cmd = ""
            else:
              new_key = string.capwords(cmd.split(" ")[0])
              new_cmd = cmd[len(new_key):]

            look_up_result = self.look_up(user_character[key],new_key,new_cmd)

            if type(look_up_result) is dict:
              self.bot.database["starwars characters"].update_one({"_id":user},
                {"$set": {key : look_up_result}})
              return "Changed " + user_character["Name"] + "'s " + key
            else:
              return look_up_result
        else:
          if cmd == "":
            self.bot.log("Retrieving data")
            if type(user_character[key]) is list:
              return key+":\n"+", ".join(user_character[key])
            else:
              return user_character[key]
          elif cmd[0] == '+':
            self.bot.log("Adding")
            try:
              cmd = cmd[1:]
              while cmd[0] == ' ':
                cmd = cmd[1:]
            except:
              self.bot.log("Error message")
              return "Can't do that"

            if type(user_character[key]) is int:
              try:
                self.bot.log("Adding "+cmd+" to "+key)
                self.bot.database["starwars characters"].update_one({"_id":user},
                  {"$inc": {key : int(cmd)}})
                return "Added " + cmd + " to " + user_character["Name"] + "'s " + key
              except:
                self.bot.log("BITCH SANDWICH")
                return "Can't add that"
            elif type(user_character[key]) is list:
              try:
                self.bot.log("Adding "+cmd+" to "+key)
                self.bot.database["starwars characters"].update_one({"_id":user},
                  {"$push": {key : cmd}})
                return "Added " + cmd + " to " + user_character["Name"] + "'s " + key
              except:
                self.bot.log("tstststststs")
                return "Can't add that"
            else:
              self.bot.log("Help")
              return "Can't add that"
          elif cmd[0] == '-':
            self.bot.log("Removing/subtracting")
            try:
              cmd = cmd[1:]
              while cmd[0] == ' ':
                cmd = cmd[1:]
            except:
              self.bot.log("lalalala ")
              return "Can't do that"

            if type(user_character[key]) is int:
              try:
                self.bot.log("Subtracting "+cmd+" from "+key)
                self.bot.database["starwars characters"].update_one({"_id":user},
                  {"$inc": {key : -int(cmd)}})
                return "Subtracted " + cmd + " from " + user_character["Name"] + "'s " + key
              except:
                self.bot.log("Tried it. Didn't want to")
                return "Can't remove that"
            elif type(user_character[key]) is list:
              try:
                self.bot.log("removing "+cmd+" from "+key)
                try:
                  self.bot.database["starwars characters"].update_one({"_id":user},
                    {"$pull": {key : cmd}})
                except:
                  self.bot.log("They can only remove stuff that's actually in the list")
                  return "Not in list"
                return "Removed " + cmd + " from " + user_character["Name"] + "'s " + key
              except:
                self.bot.log("nah")
                return "Can't remove that"
            else:
              self.bot.log("nyope")
              return "Can't remove that"
          else:
            self.bot.log("Changing "+key+" to "+cmd)
            if type(user_character[key]) is int:
              try:
                self.bot.database["starwars characters"].update_one({"_id":user},
                  {"$set": {key : int(cmd)}})
              except:
                self.bot.log("I don't wanna tho")
                return "Can't do that"
            elif type(user_character[key]) is str:
              self.bot.database["starwars characters"].update_one({"_id":user},
                {"$set": {key : cmd}})
            else:
              self.bot.log("I don't wanna tho")
              return "Can't do that"
            return "Changed " + user_character["Name"] + "'s " + key +" to " + cmd
      else:
        self.bot.log(key+" isn't in there")
        return "Couldn't find that data. Are you sure you spelled it correctly?"
    else:
      self.bot.log(user+" doesn't have a character")
      return "You don't have a character. You can make one with /starwarscharacter"

  def replace_spaces(self,cmd : str):
    with_spaces = ["Specialization Trees","Wound Threshold","Strain Threshold","Defense - Ranged","Defense - Melee","Force Rating","Core Worlds","Outer Rim","Piloting - Planetary","Piloting - Space","Ranged - Heavy","Ranged - Light","Lightsaber Characteristic","Critical Injuries","Force Powers"]
    without_spaces = ["Specialization-trees","Wound-threshold","Strain-threshold","Defense-ranged","Defense-melee","Force-rating","Core-worlds","Outer-rim","Piloting-planetary","Piloting-space","Ranged-heavy","Ranged-light","Lightsaber-characteristic","Critical-injuries","Force-powers"]

    for i, value in enumerate(without_spaces):
      cmd = cmd.replace(with_spaces[i],value)

    return cmd

  def replace_with_spaces(self,cmd : str):
    with_spaces = ["Specialization Trees","Wound Threshold","Strain Threshold","Defense - Ranged","Defense - Melee","Force Rating","Core Worlds","Outer Rim","Piloting - Planetary","Piloting - Space","Ranged - Heavy","Ranged - light","Lightsaber Characteristic","Critical Injuries","Force Powers"]
    without_spaces = ["Specialization-trees","Wound-threshold","Strain-threshold","Defense-ranged","Defense-melee","Force-rating","Core-worlds","Outer-rim","Piloting-planetary","Piloting-space","Ranged-heavy","Ranged-light","Lightsaber-characteristic","Critical-injuries","Force-powers"]

    for i, value in enumerate(without_spaces):
      cmd = cmd.replace(value,with_spaces[i])

    return cmd

  async def parse_char(self, ctx, parameters : str):
    user = f"#{ctx.author.id}"
    cmd = string.capwords(parameters.replace("+","+ ").replace("-","- ").replace(",",", "))
    return_embed = False

    cmd = self.replace_spaces(cmd)

    user_character = self.bot.database["starwars characters"].find_one({"_id":user})

    if cmd == " ":
      cmd = ""
    elif cmd != "":
      while cmd[0] == " ":
        cmd = cmd[1:]
        if cmd == "":
          break


    if cmd == "":
      if user_character != None:
        title, text = self.character_sheet(user_character)
        text = self.replace_with_spaces(text)
        return_embed = True
      else:
        self.bot.log("Makin' a character for "+self.bot.database_funcs.get_name(user))
        with open("gwendolyn/resources/star_wars/starwarstemplates.json", "r") as file_pointer:
          templates = json.load(file_pointer)
        new_char = templates["Character"]
        new_char["_id"] = user
        self.bot.database["starwars characters"].insert_one(new_char)
        await ctx.send("Character for " + self.bot.database_funcs.get_name(user) + " created")
    else:
      if cmd == "Purge":
        self.bot.log("Deleting "+self.bot.database_funcs.get_name(user)+"'s character")
        self.bot.database["starwars characters"].delete_one({"_id":user})
        await ctx.send("Character for " + self.bot.database_funcs.get_name(user) + " deleted")
      else:
        await ctx.send(self.replace_with_spaces(str(self.char_data(user,cmd))))

    if return_embed:
      embed = discord.Embed(title = title, description = text, colour=0xDEADBF)
      await ctx.send(embed = embed)



  def lightsaber_char(self,user : str):
    user_character = self.bot.database["starwars characters"].find_one({"_id":user})

    if user_character != None:
      return user_character["Lightsaber-characteristic"]

  def user_has_char(self,user : str):
    user_character = self.bot.database["starwars characters"].find_one({"_id":user})

    return user_character != None
