#===============================================
#    Sistema de Lista de Encuentros Mejorado
#           Para Pokémon Essentials v16/BES
#===============================================
# Basado en "Simple Encounter List Window" by raZ
#===============================================
# Cumple exactamente la misma función, pero une en una sola lista los encuentros:
#   - Terrestres
#   - Acuaticos
#   - Otros
# Tambien permite crear nuevas páginas custom.
# Los tipos de encuentros muestran iconos dependiendo de su exclusividad.
# Tambien usa un workaround para mostrar las formas exclusivas del mapa 
# que puedes configurar con getFormOnCreation, 
# eso significa que mostrará las formas regionales del mapa correctamente.
#===============================================

begin
PluginManager.register({
  :name    => "Lista de Encuentros",
  :version => "1",
  :credits => "Clara, raZ, Nuri Yuri, Vendily"
})
rescue;end

  
module EncounterListUI_Config
  # Configuración global
  ENCOUNTER_PAGE_NAMES = {
    :terrestrial => "Terrestres",
    :aquatic => "Acuáticos", 
    :special => "Otros",
    :custom => "Especiales"
  }
  
  
  # Configuración de iconos para tipos de encuentro
  ENCOUNTER_ICONS = {
    :day => "icon_day",      # Icono para exclusivos del día
    :night => "icon_night",  # Icono para exclusivos de la noche
    :surf => "icon_surf",    # Icono para surf
    :rod => "icon_rod",      # Icono para caña
    :headbutt => "icon_headbutt", # Icono para cabezazo
    :rocksmash => "icon_rock",     # Icono para golpe roca
    :bugcontest => "icon_bug",     # Icono para el concurso de bichos
  }

  TEXT_BASE   = Color.new(248,248,248)
  TEXT_SHADOW = Color.new(117,125,150)

  STATIC_ICON   = false #Animación del sprite del pokémon.
  
  ICON_SILHOUETTE = true #Muestra una silueta del pokemon, si no lo has visto.
                         #Desactivado muestra el icono "icon000"
  
  ICON_TONE = Tone.new(0, 0, 0, 255) #Color del icono si no tienes atrapado al poke.
                         
                         
  BG_PATH   = "/EncounterUI/encounters_bg"
end
  
  
def pbEncounterListUI(mapid = nil)
  EncounterListUI.new(mapid).startUI
end

class EncounterListUI
  #Aqui se hace la magia, puedes añadir cosas custom.
  def getCustomPages
    pages = []
    
    # Ejemplo: Pokémon que aparecen solo con cierto switch
    if $game_switches[999]  # Cambia X por tu switch
      custom_encounters = []
      [:BULBASAUR, 4, 7].each do |species|  # Tus Pokémon
        if species.is_a?(String) || species.is_a?(Symbol)
          species=getID(PBSpecies,species)
        end
        custom_encounters.push({
          :species => species,
          :icon_type => nil,  # o :custom_icon
        })
      end
      
      pages.push({
        :type => :custom,
        :name => "Página Custom",
        :encounters => custom_encounters
      })
    end
    return pages
  end
    
  def initialize(mapid = nil)
    @viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
    @viewport.z = 99999
    @sprites = {}
    @current_page = 0
    @pages = []
    $pkmn_encounters = load_data("Data/encounters.dat") if !$pkmn_encounters
    @encdata = $pkmn_encounters
    @mapid = mapid == nil ? $game_map.map_id : mapid
  end
  
  def startUI
    @sprites["background"] = IconSprite.new(0, 0, @viewport)
    @sprites["background"].setBitmap("Graphics/Pictures/#{EncounterListUI_Config::BG_PATH}")
    @sprites["background"].ox = @sprites["background"].bitmap.width / 2
    @sprites["background"].oy = @sprites["background"].bitmap.height / 2
    @sprites["background"].x = Graphics.width / 2
    @sprites["background"].y = Graphics.height / 2
    
    # Crear overlay para texto personalizado
    @sprites["textoverlay"] = BitmapSprite.new(@sprites["background"].bitmap.width, @sprites["background"].bitmap.height, @viewport)
    @sprites["textoverlay"].x = (Graphics.width - @sprites["background"].bitmap.width) / 2
    @sprites["textoverlay"].y = (Graphics.height - @sprites["background"].bitmap.height) / 2
    @sprites["textoverlay"].z = @sprites["background"].z + 1
    
    @h = (Graphics.height - @sprites["background"].bitmap.height) / 2
    @w = (Graphics.width - @sprites["background"].bitmap.width) / 2

    loadAllPages
    
    if @pages.empty?
      drawAllTexts(_INTL("Ninguno"))
    else
      @sprites["rightarrow"] = AnimatedSprite.new("Graphics/Pictures/rightarrow", 8, 40, 28, 2, @viewport)
      @sprites["rightarrow"].x = Graphics.width - @sprites["rightarrow"].bitmap.width
      @sprites["rightarrow"].y = Graphics.height / 2 - @sprites["rightarrow"].bitmap.height / 16
      @sprites["rightarrow"].visible = @pages.length > 1
      @sprites["rightarrow"].play
      
      @sprites["leftarrow"] = AnimatedSprite.new("Graphics/Pictures/leftarrow", 8, 40, 28, 2, @viewport)
      @sprites["leftarrow"].x = 0
      @sprites["leftarrow"].y = Graphics.height / 2 - @sprites["rightarrow"].bitmap.height / 16
      @sprites["leftarrow"].visible = false
      @sprites["leftarrow"].play
      loadCurrentPage
    end
    main
  end
  
  def loadAllPages
    @pages = []
    return unless @encdata.is_a?(Hash) && @encdata[@mapid]
    enc = @encdata[@mapid][1]
    return unless enc
    # Página de encuentros terrestres
    terrestrial_encounters = getTerrestrialEncounters(enc)
    if !terrestrial_encounters.empty?
      @pages.push({
        :type => :terrestrial,
        :name => EncounterListUI_Config::ENCOUNTER_PAGE_NAMES[:terrestrial],
        :encounters => terrestrial_encounters
      })
    end
    # Página de encuentros acuáticos
    aquatic_encounters = getAquaticEncounters(enc)
    if !aquatic_encounters.empty?
      @pages.push({
        :type => :aquatic,
        :name => EncounterListUI_Config::ENCOUNTER_PAGE_NAMES[:aquatic],
        :encounters => aquatic_encounters
      })
    end
    # Página de encuentros especiales
    special_encounters = getSpecialEncounters(enc)
    if !special_encounters.empty?
      @pages.push({
        :type => :special,
        :name => EncounterListUI_Config::ENCOUNTER_PAGE_NAMES[:special],
        :encounters => special_encounters
      })
    end
    # Páginas personalizadas
    custom_pages = getCustomPages
    custom_pages.each do |page|
      @pages.push(page) if !page[:encounters].empty?
    end
  end
  
  
  def getTerrestrialEncounters(enc)
    encounters = []
    # Obtener listas de encuentros terrestres
    land_encounters = enc[EncounterTypes::Land] ? getListOfEncounters(enc[EncounterTypes::Land]) : []
    night_encounters = enc[EncounterTypes::LandNight] ? getListOfEncounters(enc[EncounterTypes::LandNight]) : []
    morning_encounters = enc[EncounterTypes::LandMorning] ? getListOfEncounters(enc[EncounterTypes::LandMorning]) : []
    day_encounters = enc[EncounterTypes::LandDay] ? getListOfEncounters(enc[EncounterTypes::LandDay]) : []
    cave_encounters = enc[EncounterTypes::Cave] ? getListOfEncounters(enc[EncounterTypes::Cave]) : []
    # Determinar qué listas usar para día y noche
    day_list = []
    night_list = []
    if !day_encounters.empty?
      day_list = day_encounters # Si existe LandDay, usarlo como encuentros de día
    elsif !land_encounters.empty?
      day_list = land_encounters # Si no existe LandDay, Land actúa como encuentros de día
    end
    if !night_encounters.empty?
      night_list = night_encounters # Si existe LandNight, usarlo como encuentros de noche
    end
    # Crear lista de todos los Pokémon únicos
    all_species = (day_list + night_list + cave_encounters).uniq
    all_species.each do |species|
      icon_type = nil
      # Solo mostrar iconos si hay encuentros tanto de día como de noche
      if !day_list.empty? && !night_list.empty?
        if day_list.include?(species) && !night_list.include?(species)
          icon_type = :day # Solo aparece de día
        elsif night_list.include?(species) && !day_list.include?(species)
          icon_type = :night # Solo aparece de noche
        end
      end
      # Si solo hay encuentros de día O solo de noche, no hay iconos
      encounters.push({
        :species => species,
        :icon_type => icon_type,
      })
    end
    return encounters
  end

  def getAquaticEncounters(enc)
    encounters = []
    # Obtener listas de encuentros acuáticos
    surf_encounters = enc[EncounterTypes::Water] ? getListOfEncounters(enc[EncounterTypes::Water]) : []
    old_rod_encounters = enc[EncounterTypes::OldRod] ? getListOfEncounters(enc[EncounterTypes::OldRod]) : []
    good_rod_encounters = enc[EncounterTypes::GoodRod] ? getListOfEncounters(enc[EncounterTypes::GoodRod]) : []
    super_rod_encounters = enc[EncounterTypes::SuperRod] ? getListOfEncounters(enc[EncounterTypes::SuperRod]) : []
    # Combinar todos los encuentros de pesca
    all_rod_encounters = (old_rod_encounters + good_rod_encounters + super_rod_encounters).uniq
    # Crear lista de todos los Pokémon acuáticos únicos
    all_aquatic_species = (surf_encounters + all_rod_encounters).uniq
    all_aquatic_species.each do |species|
      icon_type = nil
      if surf_encounters.include?(species) && !all_rod_encounters.include?(species)
        icon_type = :surf # Solo aparece en surf
      elsif all_rod_encounters.include?(species) && !surf_encounters.include?(species)
        icon_type = :rod # Solo aparece pescando
      #elsif surf_encounters.include?(species) && all_rod_encounters.include?(species)
        # Aparece tanto en surf como pescando - sin icono especial
      end
      encounters.push({
        :species => species,
        :icon_type => icon_type,
      })
    end
    
    return encounters
  end
  
  def getSpecialEncounters(enc)
    encounters = []
    # Concurso bichos
    if enc[EncounterTypes::BugContest] # RockSmash
      bug_encounters = getListOfEncounters(enc[EncounterTypes::BugContest])
      bug_encounters.each do |species|
        encounters.push({
          :species => species,
          :icon_type => :bugcontest,
        })
      end
    end
    # Golpe Roca
    if enc[EncounterTypes::RockSmash] # RockSmash
      rock_encounters = getListOfEncounters(enc[EncounterTypes::RockSmash])
      rock_encounters.each do |species|
        encounters.push({
          :species => species,
          :icon_type => :rocksmash,
        })
      end
    end
    # Cabezazo común
    if enc[EncounterTypes::HeadbuttLow] # HeadbuttLow
      headbutt_low_encounters = getListOfEncounters(enc[EncounterTypes::HeadbuttLow])
      headbutt_low_encounters.each do |species|
        encounters.push({
          :species => species,
          :icon_type => :headbutt,
        })
      end
    end
    # Cabezazo raro
    if enc[EncounterTypes::HeadbuttHigh] # HeadbuttHigh
      headbutt_high_encounters = getListOfEncounters(enc[EncounterTypes::HeadbuttHigh])
      headbutt_high_encounters.each do |species|
        next if hasSpeciesInArray(encounters, species)
        encounters.push({
          :species => species,
          :icon_type => :headbutt,
        })
      end
    end
    return encounters
  end
    
  def getListOfEncounters(encounter)
    return [] unless encounter
    encable = encounter.compact
    encable.map! {|enc| enc[0]}
    encable.flatten!
    encable.uniq!
    return encable
  end
  
  def hasSpeciesInArray(encounters_array, species)
    encounters_array.each do |enc|
      return true if enc[:species] == species
    end
    return false
  end
    
  def loadCurrentPage
    clearIconSprites
    return if @pages.empty?
    page = @pages[@current_page]
    encounters = page[:encounters]
    # Calcular conteo de capturados
    i = 0
    ownerCount = 0
    encounters.each do |encounter_data|
      species = encounter_data[:species]
      icon_type = encounter_data[:icon_type]
      createPokemonIcon(i, species)
      createTypeIcon(i, icon_type) if icon_type
      ownerCount += 1 if $Trainer.hasOwned?(species)
      i += 1
    end
    drawAllTexts(page[:name], encounters, i)
    updateArrows
  end
  
  def drawAllTexts(page_name, encounters=nil, owned=0)
    # Limpiar bitmap anterior
    @sprites["textoverlay"].bitmap.clear
    
    # Configuración de fuentes y colores
    title_base   = EncounterListUI_Config::TEXT_BASE  
    title_shadow = EncounterListUI_Config::TEXT_SHADOW
    info_base    = EncounterListUI_Config::TEXT_BASE  
    info_shadow  = EncounterListUI_Config::TEXT_SHADOW

    # Texto del título (Nombre del mapa : Tipo de página)
    title_x = @sprites["textoverlay"].bitmap.width / 2
    title_y = 8
    pbSetSystemFont(@sprites["textoverlay"].bitmap)
    pbDrawTextPositions(@sprites["textoverlay"].bitmap, [
        [_INTL("{1} : {2}",pbGetMapNameFromId(@mapid),page_name), title_x, title_y, 2, title_base, title_shadow]
    ])  
    # Texto de información (Especies y capturados)
    info_x = @sprites["textoverlay"].bitmap.width / 2
    info_y = title_y + 32 #@sprites["textoverlay"].bitmap.height - 40
    pbSetSmallFont(@sprites["textoverlay"].bitmap)

    if encounters != nil
      pbDrawTextPositions(@sprites["textoverlay"].bitmap, [
        [_INTL("Especies: {1}      Capturados: {2}",encounters.length,owned), info_x, info_y, 2, info_base, info_shadow]])
      else
      pbDrawTextPositions(@sprites["textoverlay"].bitmap, [
        [_INTL("¡Esta zona no tiene Pokémon salvajes!"), info_x, info_y, 2, info_base, info_shadow]])
 
    end
  end
  
  def createPokemonIcon(index, species, form)
    if !$Trainer.hasSeen?(species) && !$Trainer.hasOwned?(species)
      @sprites["icon_#{index}"] = PokemonSpeciesIconSprite.new(0, @viewport)
    elsif !$Trainer.hasOwned?(species)
      @sprites["icon_#{index}"] = PokemonSpeciesIconSprite.new(species, @viewport)
      @sprites["icon_#{index}"].pbSetParams(species, 0, form)
      @sprites["icon_#{index}"].tone = Tone.new(0, 0, 0, 255)
    else
      @sprites["icon_#{index}"] = PokemonSpeciesIconSprite.new(species, @viewport)
      @sprites["icon_#{index}"].pbSetParams(species, 0, form)
    end
    
    # Posicionar iconos en filas
    row = index / 7
    col = index % 7
    
    @sprites["icon_#{index}"].x = @w + 28 + (64 * col)
    @sprites["icon_#{index}"].y = @h + 120 + (64 * row)
  end

  def createPokemonIcon(index, species)
    dummy_pokemon = PokeBattle_Pokemon.new(species, 1) # Crear un Pokémon para obtener la forma correcta.
    sprite = PokemonIconSprite.new(dummy_pokemon, @viewport,EncounterListUI_Config::STATIC_ICON)  # Normal
    if !$Trainer.hasSeen?(species) && EncounterListUI_Config::ICON_SILHOUETTE
      sprite.tone = Tone.new(-255, -255, -255, 255)  # Silueta
    elsif $Trainer.hasSeen?(species) && !$Trainer.hasOwned?(species)
      sprite.tone = EncounterListUI_Config::ICON_TONE  # Tono para solo visto
    elsif $Trainer.hasSeen?(species) || $Trainer.hasOwned?(species)
      
    else
      sprite = PokemonSpeciesIconSprite.new(0, @viewport)  # Placeholder por defecto
    end
    @sprites["icon_#{index}"] = sprite

    # Posicionar iconos en filas
    row = index / 7
    col = index % 7
    @sprites["icon_#{index}"].x = @w + 28 + (64 * col)
    @sprites["icon_#{index}"].y = @h + 56 + (64 * row)
  end
  
  def createTypeIcon(index, icon_type)
    return unless EncounterListUI_Config::ENCOUNTER_ICONS[icon_type]
    @sprites["type_#{index}"] = IconSprite.new(0, 0, @viewport)
    begin
      @sprites["type_#{index}"].setBitmap("Graphics/Pictures/EncounterUI/#{EncounterListUI_Config::ENCOUNTER_ICONS[icon_type]}")
      if @sprites["type_#{index}"].bitmap
        icon_width = @sprites["type_#{index}"].bitmap.width 
        icon_height = @sprites["type_#{index}"].bitmap.height
      end
      pokemon_sprite = @sprites["icon_#{index}"]
      @sprites["type_#{index}"].x = pokemon_sprite.x + (64 - icon_width)
      @sprites["type_#{index}"].y = pokemon_sprite.y + (64 - icon_height)
    rescue
      @sprites["type_#{index}"].dispose
      @sprites.delete("type_#{index}")
    end
  end
  
  def clearIconSprites
    @sprites.keys.each do |key|
      next unless key.include?("icon_") || key.include?("type_")
      @sprites[key].dispose
      @sprites.delete(key)
    end
  end
  
  def updateArrows
    if @pages.length <= 1
      @sprites["leftarrow"].visible = false
      @sprites["rightarrow"].visible = false
    else
      @sprites["leftarrow"].visible = @current_page > 0
      @sprites["rightarrow"].visible = @current_page < @pages.length - 1
    end
  end
  
  def main
    loop do
      Graphics.update
      Input.update
      update
      if Input.trigger?(Input::RIGHT) && @current_page < @pages.length - 1
        pbPlayCursorSE
        @current_page += 1
        loadCurrentPage
      elsif Input.trigger?(Input::LEFT) && @current_page > 0
        pbPlayCursorSE
        @current_page -= 1
        loadCurrentPage
      elsif Input.trigger?(Input::C) || Input.trigger?(Input::B)
        Input.update
        break
      end
    end
    dispose
  end
  
  def update
    pbUpdateSpriteHash(@sprites)
  end
    
  def dispose
    pbFadeOutAndHide(@sprites)
    pbDisposeSpriteHash(@sprites)
    @viewport.dispose
  end
end