#===============================================================================
#Sistema de Autosave de Kyu
#Interruptor que desactiva el autosave.
NOAUTOSAVESWITCH = 999

#Activa/Desactiva la animación que avisa del autoguardado.
AUTOSAVEANIMATION = true
#===============================================================================

class PokemonLoad
  ##### Autosave #############################################
  def pbTryLoadFile(savefile, backup=false)
    trainer=nil
    framecount=nil
    game_system=nil
    pokemonSystem=nil
    mapid=nil
    time=nil
    File.open(savefile){|f|
       if backup
         Marshal.load(f)
       end
       trainer=Marshal.load(f)
       framecount=Marshal.load(f)
       game_system=Marshal.load(f)
       pokemonSystem=Marshal.load(f)
       mapid=Marshal.load(f)
       time=Marshal.load(f)
    }
    raise "Archivo corrupto" if !trainer.is_a?(PokeBattle_Trainer)
    raise "Archivo corrupto" if !framecount.is_a?(Numeric)
    raise "Archivo corrupto" if !game_system.is_a?(Game_System)
    raise "Archivo corrupto" if !pokemonSystem.is_a?(PokemonSystem)
    raise "Archivo corrupto" if !mapid.is_a?(Numeric)
    return [trainer,framecount,game_system,pokemonSystem,mapid,time]
  end
  #######################################################

  def pbStartLoadScreen
    $PokemonTemp   = PokemonTemp.new
    $game_temp     = Game_Temp.new
    $game_system   = Game_System.new
    $PokemonSystem = PokemonSystem.new if !$PokemonSystem
    cmdContinue    = -1
    cmdNewGame     = -1
    cmdOption      = -1
    cmdLanguage    = -1
    cmdMysteryGift = -1
    cmdQuit        = -1
    cmdBackup      = -1
    commands       = []
    
    savefile = RTP.getSaveFileName("Game.rxdata")
    #FontInstaller.install #DISABLED - BES
    data_system = pbLoadRxData("Data/System")
    mapfile=sprintf("Data/Map%03d.rxdata",data_system.start_map_id)
    if data_system.start_map_id==0 || !pbRgssExists?(mapfile)
      Kernel.pbMessage(_INTL("No se estableció una posición inicial en el mapa.\1"))
      Kernel.pbMessage(_INTL("El juego no puede continuar."))
      @scene.pbEndScene
      $scene=nil
      return
    end
    if safeExists?(savefile)
      trainer=nil
      framecount=0
      mapid=0
      showContinue=false
      haveBackup=false
      begin
        trainer, framecount, $game_system, $PokemonSystem, mapid=pbTryLoadFile(savefile)
        showContinue=true
      rescue
        if safeExists?(savefile+".bak")
          begin
            trainer, framecount, $game_system, $PokemonSystem, mapid=pbTryLoadFile(savefile+".bak")
            haveBackup=true
            showContinue=true
          rescue
          end
        end
        if haveBackup
          Kernel.pbMessage(_INTL("El archivo guardado está corrupto. Se cargará el archivo guardado previo."))
        else
          Kernel.pbMessage(_INTL("El archivo guardado está corrupto o es incompatible con este juego."))
          if !Kernel.pbConfirmMessageSerious(_INTL("¿Quieres borrar el archivo guardado para iniciar uno nuevo?"))
            raise "scss error - Corrupted or incompatible save file."
          end
          begin; File.delete(savefile); rescue; end
          begin; File.delete(savefile+".bak"); rescue; end
          $game_system=Game_System.new
          $PokemonSystem=PokemonSystem.new if !$PokemonSystem
          Kernel.pbMessage(_INTL("El archivo guardado fue borrado."))
        end
      end
      if showContinue
        if !haveBackup
          begin; File.delete(savefile+".bak"); rescue; end
        end
      end
      commands[cmdContinue=commands.length]=_INTL("Continuar") if showContinue
      commands[cmdBackup=commands.length]=_INTL("Autoguardados") if showContinue
      commands[cmdNewGame=commands.length]=_INTL("Partida Nueva")
      commands[cmdMysteryGift=commands.length]=_INTL("Regalo Misterioso") if (trainer.mysterygiftaccess rescue false) || MYSTERYGIFTALWAYSSHOW
    else
      commands[cmdNewGame=commands.length]=_INTL("Partida Nueva")
      commands[cmdBackup=commands.length]=_INTL("Autoguardados") if safeExists?(RTP.getSaveFileName("Backup0.rxdata"))
    end
    commands[cmdOption=commands.length]=_INTL("Opciones")
    commands[cmdLanguage=commands.length]=_INTL("Idioma") if LANGUAGES.length>=2
    commands[cmdQuit=commands.length]=_INTL("Salir del Juego")
    @scene.pbStartScene(commands,showContinue,trainer,framecount,mapid)
    @scene.pbSetParty(trainer) if showContinue
    @scene.pbStartScene2
    $ItemData = readItemList("Data/items.dat")
    loop do
      command=@scene.pbChoose(commands)

    if (cmdContinue>=0 && command==cmdContinue) || (cmdBackup>=0 && command == cmdBackup)
       # Autosave ###########################################
       if command == cmdBackup
         commands = []
         for i in 0...10
           file = RTP.getSaveFileName("Backup#{i}.rxdata")
           if safeExists?(file)
             data = nil
             File.open(file){|f|
               data = Marshal.load(f)
             }
             if data.is_a?(String)
               commands.push(data)
               next
             end
           end
           commands.push("----------")
         end
         cmd = selectAutosave(commands)
         if cmd == nil
           next
         end
         savefile = RTP.getSaveFileName("Backup#{cmd}.rxdata")
         trainer, framecount, $game_system, $PokemonSystem, mapid=pbTryLoadFile(savefile, true)
         $loading = true
       end
       ####################################################
        unless safeExists?(savefile)
          pbPlayBuzzerSE()
          next
        end
        @scene.pbEndScene
        metadata=nil
        
        File.open(savefile){|f|
          #### Autosave ############
          if command==cmdBackup
            Marshal.load(f) # Backup data already loaded
          end
          ###########################
           Marshal.load(f) # Trainer already loaded
           $Trainer             = trainer
           Graphics.frame_count = Marshal.load(f)
           $game_system         = Marshal.load(f)
           Marshal.load(f) # PokemonSystem already loaded
           Marshal.load(f) # Current map id no longer needed
           $game_switches       = Marshal.load(f)
           $game_variables      = Marshal.load(f)
           $game_self_switches  = Marshal.load(f)
           $game_screen         = Marshal.load(f)
           $MapFactory          = Marshal.load(f)
           $game_map            = $MapFactory.map
           $game_player         = Marshal.load(f)
           $PokemonGlobal       = Marshal.load(f)
           metadata             = Marshal.load(f)
           $PokemonBag          = Marshal.load(f)
           $PokemonStorage      = Marshal.load(f)
           magicNumberMatches=false
           if $data_system.respond_to?("magic_number")
             magicNumberMatches=($game_system.magic_number==$data_system.magic_number)
           else
             magicNumberMatches=($game_system.magic_number==$data_system.version_id)
           end
           if !magicNumberMatches || $PokemonGlobal.safesave
             if pbMapInterpreterRunning?
               pbMapInterpreter.setup(nil,0)
             end
             begin
               $MapFactory.setup($game_map.map_id) # calls setMapChanged
             rescue Errno::ENOENT
               if $DEBUG
                 Kernel.pbMessage(_INTL("No se encontró el mapa {1}.",$game_map.map_id))
                 map=pbWarpToMap()
                 if map
                   $MapFactory.setup(map[0])
                   $game_player.moveto(map[1],map[2])
                 else
                   $game_map=nil
                   $scene=nil
                   return
                 end
               else
                 $game_map=nil
                 $scene=nil
                 Kernel.pbMessage(_INTL("No se encontró el mapa. El juego no puede continuar."))
               end
             end
             $game_player.center($game_player.x, $game_player.y)
           else
             $MapFactory.setMapChanged($game_map.map_id)
           end
        }
        if !$game_map.events # Map wasn't set up
          $game_map=nil
          $scene=nil
          Kernel.pbMessage(_INTL("El mapa está corrupto. El juego no puede continuar."))
          return
        end
        $PokemonMap=metadata
        $PokemonEncounters=PokemonEncounters.new
        $PokemonEncounters.setup($game_map.map_id)
        pbAutoplayOnSave
        $game_map.update
        $PokemonMap.updateMap
        $scene = Scene_Map.new
        return
      elsif cmdNewGame>=0 && command==cmdNewGame
        @scene.pbEndScene
        if $game_map && $game_map.events
          for event in $game_map.events.values
            event.clear_starting
          end
        end
        $game_temp.common_event_id=0 if $game_temp
        $scene               = Scene_Map.new
        Graphics.frame_count = 0
        $game_system         = Game_System.new
        $game_switches       = Game_Switches.new
        $game_variables      = Game_Variables.new
        $game_self_switches  = Game_SelfSwitches.new
        $game_screen         = Game_Screen.new
        $game_player         = Game_Player.new
        $PokemonMap          = PokemonMapMetadata.new
        $PokemonGlobal       = PokemonGlobalMetadata.new
        $PokemonStorage      = PokemonStorage.new
        $PokemonEncounters   = PokemonEncounters.new
        $PokemonTemp.begunNewGame=true
        $data_system         = pbLoadRxData("Data/System")
        $MapFactory          = PokemonMapFactory.new($data_system.start_map_id) # calls setMapChanged
        $game_player.moveto($data_system.start_x, $data_system.start_y)
        $game_player.refresh
        $game_map.autoplay
        $game_map.update
        return
      elsif cmdMysteryGift>=0 && command==cmdMysteryGift
        pbFadeOutIn(99999){
           trainer=pbDownloadMysteryGift(trainer)
        }
      elsif cmdOption>=0 && command==cmdOption
        scene=PokemonOptionScene.new
        screen=PokemonOption.new(scene)
        pbFadeOutIn(99999) { screen.pbStartScreen(true) }
      elsif cmdLanguage>=0 && command==cmdLanguage
        @scene.pbEndScene
        $PokemonSystem.language=pbChooseLanguage
        pbLoadMessages("Data/"+LANGUAGES[$PokemonSystem.language][1])
        savedata=[]
        if safeExists?(savefile)
          File.open(savefile,"rb"){|f|
             15.times { savedata.push(Marshal.load(f)) }
          }
          savedata[3]=$PokemonSystem
          begin
            File.open(RTP.getSaveFileName("Game.rxdata"),"wb"){|f|
               15.times {|i| Marshal.dump(savedata[i],f) }
            }
          rescue
          end
        end
        $scene=pbCallTitle
        return
      elsif cmdQuit>=0 && command==cmdQuit
        @scene.pbEndScene
        $scene=nil
        return
      end
    end
    @scene.pbEndScene
    return
  end
end

def selectAutosave(commands)
  cmdwindow=Window_CommandPokemonEx.new(commands)
  cmdwindow.z=99999
  cmdwindow.visible=true
  cmdwindow.resizeToFit(cmdwindow.commands)
  cmdwindow.index=0
  cmdwindow.x = Graphics.width/2 - cmdwindow.width/2
  cmdwindow.y = Graphics.height/2 - cmdwindow.height/2
  command = 0
  loop do
    Graphics.update
    Input.update
    cmdwindow.update
    if Input.trigger?(Input::B)
      command = nil
      break
    end
    if Input.trigger?(Input::C)
      if commands[cmdwindow.index] == "----------"
        Kernel.pbMessage("No existe respaldo para este slot")
      else
        command=cmdwindow.index
        break
      end
    end
  end
  cmdwindow.dispose
  Input.update
  return command
end
 
def pbSave(safesave=false, backup=false)
  return if !$Trainer
  $Trainer.metaID=$PokemonGlobal.playerID
    if backup
      index = $PokemonGlobal.autosaveSlot
      savefile = RTP.getSaveFileName("Backup#{index}.rxdata")
      time = Time.now.strftime("%c") #pbGetTimeNow.strftime("%c")
      mapname = pbGetMapNameFromId($game_map.map_id)
      data = _INTL("{1} - {2}", mapname[0,25], time)
      $PokemonGlobal.autosaveSlot += 1
    else
      savefile = RTP.getSaveFileName("Game.rxdata")
    end
  begin
    File.open(savefile,"wb"){|f|
       if backup
         Marshal.dump(data,f)
       end
       Marshal.dump($Trainer,f)
       Marshal.dump(Graphics.frame_count,f)
       if $data_system.respond_to?("magic_number")
         $game_system.magic_number = $data_system.magic_number
       else
         $game_system.magic_number = $data_system.version_id
       end
       $game_system.save_count+=1
       Marshal.dump($game_system,f)
       Marshal.dump($PokemonSystem,f)
       Marshal.dump($game_map.map_id,f)
       Marshal.dump($game_switches,f)
       Marshal.dump($game_variables,f)
       Marshal.dump($game_self_switches,f)
       Marshal.dump($game_screen,f)
       Marshal.dump($MapFactory,f)
       Marshal.dump($game_player,f)
       $PokemonGlobal.safesave=safesave
       Marshal.dump($PokemonGlobal,f)
       Marshal.dump($PokemonMap,f)
       Marshal.dump($PokemonBag,f)
       Marshal.dump($PokemonStorage,f)
    }
    Graphics.frame_reset
  rescue
    return false
  end
  return true
end
 
Events.onMapSceneChange+=proc{|sender,e|
  scene=e[0]
  mapChanged=e[1]
  if !$game_switches[NOAUTOSAVESWITCH]
    return if !scene || !scene.spriteset
    if mapChanged
      if $loading == false # Not loading for the first time
        pbSave(false, true)
        autosaveAnim if AUTOSAVEANIMATION
      end
      $loading = false
    end
  end
}
 
class PokemonGlobalMetadata #Añade la variable global AutosaveSlot
  alias ats_initialize initialize
  def initialize
    ats_initialize
    @autosaveSlot ||= 0
  end
  
  def autosaveSlot=(value)
    if value>=10
      value = 0
    end
    @autosaveSlot = value
  end
  
  def autosaveSlot
    if @autosaveSlot
      return @autosaveSlot
    else
      @autosaveSlot ||= 0
      return @autosaveSlot
    end
  end
end
 
if !defined?(UISprite)
  #UI Object with timer, animation and other relevant data
  class UISprite < SpriteWrapper
    attr_accessor :scroll
    attr_accessor :timer
   
    def initialize(x, y, bitmap, viewport)
      super(viewport)
      self.bitmap = bitmap
      self.x = x
      self.y = y
      @scroll = false
      @timer = 0
    end
   
    def update
      return if self.disposed?
      @timer += 1
      case @timer
      when (0..10)
        self.x += self.bitmap.width/10
      when (130..140)
        self.x -= self.bitmap.width/10
      when 141
        self.dispose
      end
    end
  end
   
   
  class Spriteset_Map
    # Handles all UI objects in order to control their positions on screen, timing 
    # and disposal. Acts like a Queue.
    class UIHandler
      def initialize
        @viewport = Viewport.new(0,0,Graphics.width,Graphics.height) # Uses its own viewport to make it compatible with both v16 and v17.
        @viewport.z = 9999
        @sprites = []
      end
   
      def addSprite(x, y, bitmap)
        @sprites.each{|sprite|
          sprite.scroll = true
        }
        index = @sprites.length
        @sprites[index] = UISprite.new(x, y, bitmap, @viewport)
      end
   
      def update
        removed = []
        @sprites.each_index{|key|
          sprite = @sprites[key]
          if sprite.scroll
            sprite2 = @sprites[key + 1]
            if sprite.x >= sprite2.x && sprite.x <= sprite2.bitmap.width + sprite2.x
              if sprite.y >= sprite2.y && sprite.y <= sprite2.bitmap.height + sprite2.y + 5
                sprite.y += 5
              end
            else
              sprite.scroll = false
            end
          end
          sprite.update
          if sprite.disposed?
            removed.push(sprite)
          end
        }
        
        removed.each{|sprite|
          @sprites.delete(sprite)
        }
      end
          
      def dispose
        @sprites.each{|sprite|
          if !sprite.disposed?
            sprite.dispose
          end
        }
        @viewport.dispose
      end
    end
    
    alias :disposeOld :dispose
    alias :updateOld :update
   
    def dispose
      @ui.dispose if @ui
      disposeOld
    end
   
    def update
      @ui = UIHandler.new if !@ui
      @ui.update
      updateOld
    end
   
    def ui
      return @ui
    end
  end
   
  class Scene_Map
    def addSprite(x, y, bitmap)
      self.spriteset.ui.addSprite(x, y, bitmap)
    end
  end
end
 
def autosaveAnim
  bitmap = Bitmap.new(Graphics.width, 50)
  pbSetSystemFont(bitmap)
  base = Color.new(28,227,43)
  shadow = Color.new(72,80,88,0)
  #bitmap.font.size = 20
  pbSetSmallFont(bitmap)
  textpos = [[_INTL("Autoguardado Completado"),10,15,0,base,shadow]]
  pbDrawTextPositions(bitmap,textpos)
  $scene.addSprite(-bitmap.width,Graphics.height-60,bitmap)
end
