gen = require './generations'
{_} = require 'underscore'
database = require('./database')

FormatsClass = require '../shared/conditions'
Formats = FormatsClass.Formats()
pokemonArr = []
hasmega = false
UberCount = 0
PUCount = 0
UnreleasedCount = 0
DeltaCount = 0
generation = ""

createTeamBookshelf = (format, requs, next) ->
  createTeam format, requs, (mons, teamname) ->
    team = {}
    team.name = teamname
    team.id = Math.floor(Math.random() * (10000000) + 10000000)
    team.generation = Formats[format].generation
    team.pokemon = mons

    attributes = _.pick(team, 'id', 'name', 'generation')
    attributes['trainer_id'] = 1
    attributes['contents'] = JSON.stringify(mons)

    Team = new database.Team(attributes)
    next(Team)

createTeam = (format, requs, next) ->
  pokemonArr = []
  hasmega = false
  UberCount = 0
  PUCount = 0
  UnreleasedCount = 0
  DeltaCount = 0

  genTeam = ->
    conditions = Formats[format]
    if conditions.tierBased == false
      console.log("PBV is not supported")
      return
      #throw error
    generation = conditions.generation.toUpperCase()
    for condNum in conditions.conditions
      for conditionName, conditionNumber of FormatsClass.Conditions
        if conditionNumber is condNum
          if /TIER_/.test(conditionName)
            tier = conditionName.replace /TIER_/, ""
            break    
    getValidFormes generation, tier, (list) ->
       if list.length < 6
         console.log("Not enough pokemon in this tier to make a team")
         return
       getPokemonArr = ->
         if pokemonArr.length < 6
           generatePokemon list, generation, requs, (pkmn) ->
             pokemonArr.push(pkmn)
             if (pkmn.tier == ["Uber"])
               UberCount++
             else if (pkmn.tier == ["PU"])
               PUCount++
             if _.has pkmn, "unreleased" and pkmn.unreleased is true
               UnreleasedCount++
             if /Delta/.test(pkmn.species)
               DeltaCount++
             getPokemonArr()
       getPokemonArr()

       pokemonArr.splice(6)

       err = require('./conditions').validateTeam(requs, pokemonArr, gen.GenerationJSON[generation])
       if err.length > 0
         console.log(err)
         genTeam()
         return
       teamname = "Random"
       next(pokemonArr, teamname)
  genTeam()
  
getValidFormes = (generation, tier, next) ->
  filteredlist = []
  fullList = gen.GenerationJSON[generation].RandomList
  for pok in fullList
    #If has random moves to choose from
    if (_.has pok, "randomMoves") and pok.randomMoves.length >= 4
      filteredlist.push(pok)
  next(filteredlist)
  

generatePokemon = (list, generation, requs, next) ->

  tryGenerate = ->
    #Generate a random pokemon
    pokemon = list[Math.floor(Math.random() * (list.length))]
    
    for teamMember in pokemonArr
      #reject if we already have this species
      if pokemon.Name is teamMember.species
        tryGenerate()
        return
      #reject if we already have a mega
      if /mega/.test(pokemon.Forme) and hasmega
        tryGenerate()
        return

    #reject based on Uber count, PU count or unreleased count
    if UberCount > 1 and pokemon.tier[0] is "Uber" and Math.floor(Math.random() * 5) > 0
      tryGenerate()
      return
    if PUCount > 1 and pokemon.tier[0] is "PU" and Math.floor(Math.random() * 5) > 0
      tryGenerate()
      return
    if UnreleasedCount > 1 and _.has pokemon, "unreleased" and pokemon.unreleased is true and Math.floor(Math.random() * 5) > 0
      tryGenerate()
      return
    if pokemon.tier[0] is "LC" or pokemon.tier[0] is "AG"
      tryGenerate()
      return
    if DeltaCount is 0 and !(/Delta/.test(pokemon.Name)) and Math.floor(Math.random() * 10) != 0
      tryGenerate()
      return

    #Special code for mega eevee, we need the data for the default
    if pokemon.Name is "Eevee" and /mega-/.test(pokemon.Forme)
      Obj.forme = "mega"
      pokemon = gen.GenerationJSON[generation].FormeData[pokemon.Name]["mega"]

    Obj = {}
    Obj.species = pokemon.Name
    #Generate moves through different function
    possibleMoves = pokemon.randomMoves
    Obj.moves = generateMoves(possibleMoves)

    #Get forme
    if pokemon.isBattleOnly
      #gotta give it a megastone if it's a mega
      if /mega/.test(pokemon.Forme)
        itemList = gen.GenerationJSON[generation].ItemData
        for item, itemdata of itemList
          if _.has itemdata, "mega"
            if itemdata.mega[0] is pokemon.Name and itemdata.mega[1] is pokemon.Forme
              Obj.item = item
              hasmega = true
              break
      #gotta handle itembased mons
      if pokemon.isItemBased
        itemList = gen.GenerationJSON[generation].ItemData
        for item, itemdata of itemList
          if _.has itemdata, "itemForme"
            if itemdata.itemForme[0] is pokemon.Name and itemdata.itemForme[1] is pokemon.Forme
              Obj.item = item
              break
      if !pokemon.isItemBased
        Obj.forme = "default" 
        pokemon = gen.GenerationJSON[generation].FormeData[pokemon.Name]["default"] if !pokemon.isItemBased
      else
        Obj.forme = pokemon.Forme
    else
      Obj.forme = pokemon.Forme

    #Assign ability
    abiInt = 0
    if _.has pokemon, "hiddenAbility"
      abiInt = 1
    abilityRan = Math.floor(Math.random() * (pokemon.abilities.length + abiInt))
    if abilityRan is pokemon.abilities.length
      Obj.ability = pokemon.hiddenAbility
    else
      Obj.ability = pokemon.abilities[abilityRan]

    natureArray = ["Hardy","Lonely","Brave","Adamant","Naughty","Bold","Docile","Relaxed","Impish","Lax","Timid","Hasty","Serious","Jolly","Naive","Modest","Mild","Quiet","Bashful","Rash","Calm","Gentle","Sassy","Careful","Quirky"]
    Obj.nature = natureArray[Math.floor(Math.random() * (natureArray.length))]

    Obj.level = gen.GenerationJSON[generation].maxLevel
    Obj.happiness = 100
  
    Obj.evs = { hp: 84, specialAttack:85, speed:84, attack:85,defense:85,specialDefense:85 }

    #determine if a move is Hidden Power, to determine IVs
    hiddenPower = "none"
    integer = 0
    for pmove in Obj.moves
      if /Hidden Power/.test(pmove)
        hiddenPower = pmove.replace /Hidden Power /, ""
        Obj.moves[integer] = "Hidden Power"
      integer = integer + 1
    Obj.ivs = determineIVs(hiddenPower)

    err = require('./conditions').validatePokemon(requs, Obj, gen.GenerationJSON[generation], "")
    if err > 0
      console.log(err)
      tryGenerate()
      return
    next(Obj)
  tryGenerate()

generateMoves = (possibleMoves) ->
  movesArr = []
  generateMove = ->
    if movesArr.length < 4
      moveIndex = Math.floor(Math.random() * (possibleMoves.length))
      movename = possibleMoves[moveIndex]
      moveobj = gen.GenerationJSON[generation].MoveData[movename]
      if typeof moveobj ==  "undefined" and !(/Hidden Power/.test(movename))
        console.log(movename)
        generateMove()
        return
      #We reject the move if it's not defined
      if typeof movename ==  "undefined"
        generateMove()
        return
      #We reject the move if we aleady have it
      for movething in movesArr
        if movething is movename
          generateMove()
          return
      #We reject the move if we already have Hidden Power
      if /Hidden Power/.test(movename)
        for movething in movesArr
          if /Hidden Power/.test(movething)
            generateMove()
            return
      movesArr.push(movename)
      generateMove()
  generateMove()
  movesArr.splice(4) #Hey man, just in case. Fucking async languages.
  return movesArr

determineIVs = (type) ->
  ivObj = {
    hp: 31,
    attack: 31,
    defense: 31,
    specialAttack: 31,
    specialDefense: 31,
    speed: 31
  }
  switch type
    when "none" then return ivObj
    when "Bug"
      ivObj.speed = 30
      ivObj.specialDefense = 30
    when "Dark" then return ivObj
    when "Dragon"
      ivObj.hp = 30
    when "Electric"
      ivObj.specialAttack = 30
    when "Fighting"
      ivObj.defense = 30
      ivObj.specialDefense = 30
      ivObj.specialAttack = 30
      ivObj.speed = 30
    when "Fire"
      ivObj.attack = 30
      ivObj.speed = 30
      ivObj.specialAttack = 30
    when "Flying"
      ivObj.speed = 30
      ivObj.specialDefense = 30
      ivObj.specialAttack = 30
    when "Ghost"
      ivObj.attack = 30
      ivObj.specialDefense = 30
    when "Grass"
      ivObj.hp = 30
      ivObj.specialAttack = 30
    when "Ground"
      ivObj.specialDefense = 30
      ivObj.specialAttack = 30
    when "Ice"
      ivObj.speed = 30
    when "Poison"
      ivObj.defense = 30
      ivObj.specialDefense = 30
      ivObj.specialAttack = 30
    when "Psychic"
      ivObj.hp = 30
      ivObj.speed = 30
    when "Rock"
      ivObj.defense = 30
      ivObj.speed = 30
      ivObj.specialDefense = 30
    when "Steel"
      ivObj.specialDefense = 30
    when "Water"
      ivObj.speed = 30
      ivObj.specialAttack = 30
  return ivObj

module.exports = {createTeamBookshelf, createTeam}
