class @BattleView extends Backbone.View
  battle_template: JST['battle']
  user_info_template: JST['battle_user_info']
  action_template: JST['battle_actions']
  team_preview_template: JST['battle_team_preview']
  battle_end_template: JST['battle_end']
  battle_controls_template: JST['battle_controls']

  SPEEDS:
    Instant: 0
    Fast: 1
    Medium: 1.5
    Slow: 2

  events:
    'click .move': 'makeMove'
    'click .switch': 'switchPokemon'
    'click .mega-evolve': 'megaEvolve'
    'click .cancel': 'cancelAction'

    # After battle ends
    'click .save-replay': 'saveReplay'
    'click .save-log': 'saveLog'
    'click .return-to-lobby': 'returnToLobby'

    # Team arrangement
    'click .arrange_pokemon' : 'togglePokemonOrSwitch'
    'click .submit_arrangement': 'submitTeamPreview'

    # Battle controls
    'change .battle-speed': 'changeBattleSpeed'

  initialize: (options) =>
    @chatView = null
    @lastMove = null
    @skip     = null
    @room = PokeBattle.rooms?.add(id: @model.id, users: [])
    try
      @speed = Number(window.localStorage.getItem('battle_speed'))
    catch
    @speed ||= 1
    @listenTo(@model, 'change:teams[*].pokemon[*].status', @handleStatus)
    @listenTo(@model, 'change:teams[*].pokemon[*].percent', @handlePercent)
    @listenTo(@model, 'change:finished', @handleEnd)
    @listenTo(@model.collection, 'remove', @handleRemoval)  if @model.collection
    @battleStartTime = $.now()
    @timers = []
    @timerUpdatedAt = []
    @timerFrozenAt = []
    @timerIterations = 0
    @countdownTimers()
    @render()

  render: =>
    @renderChat()
    # rendering the battle depends on a protocol being received
    this

  renderBattle: =>
    locals =
      yourTeam     : @model.getTeam()
      opponentTeam : @model.getOpponentTeam()
      numActive    : @model.numActive
      yourIndex    : @model.get('index')
      window       : window
    @$('.battle_pane').html @battle_template(locals)
    @renderPokemon()
    @renderControls()
    this

  renderPokemon: ($images, callback) =>
    $images ||= @$('.preload')
    battle = @model
    self = this
    $images.each ->
      $this = $(this)
      $pokemon = $this.closest('.pokemon')
      [player, slot] = [$pokemon.data('team'), $pokemon.data('slot')]
      front   = $pokemon.hasClass('top')
      species = $this.data('species')
      forme   = $this.data('forme')
      shiny   = $this.data('shiny')
      gen     = battle.get('generation').toUpperCase()
      {id}    = window.Generations[gen].SpeciesData[species]
      url     = PokemonSprite(id, forme, front: front, shiny: shiny)
      scale   = if front then 0.7 else 0.9
      self.addPokemonImage $this, url, scale: scale, callback: ($image) ->
        image = $image[0]
        {width, height} = image
        [x, y] = self.getPokemonPosition(player, slot)
        x -= (width >> 1)
        y -= (height >> 1)
        y += 30 if !front
        $image.css(top: y, left: x).show()
        callback?($image)
    this

  renderControls: =>
    html = @battle_controls_template(speeds: @SPEEDS, currentSpeed: @speed)
    @$el.find('.battle-controls').html(html)
    this

  renderChat: =>
    @chatView = new ChatView(
      el: @$('.chat')
      model: @room
      noisy: true
    ).render()
    this

  # TODO: Support 2v2
  renderActions: (validActions = []) =>
    locals =
      yourTeam     : @model.getTeam()
      validActions : validActions[0] || {}
      window       : window
    $actions = @$('.battle_actions')
    $actions.html @action_template(locals)

    pokemon = @model.getPokemon(@model.get('index'), 0)
    if pokemon.getItem()?.type == 'megastone'
      $button = $actions.find('.mega-evolve')
      $button.removeClass("hidden")
      if !pokemon.canMegaEvolve()
        $button.addClass('disabled')

    $actions.find('.move.button').each (i, el) =>
      $this = $(el)
      moveName = $this.data('move-id')
      gen = @model.get('generation').toUpperCase()
      moveData = window.Generations[gen]?.MoveData[moveName]
      @movePopover($this, moveName, moveData)

    $actions.find('.switch.button').each (i, el) =>
      $this = $(el)
      slot = $this.data('slot')
      pokemon = @model.getPokemon(@model.get('index'), slot)
      @pokemonPopover($this, pokemon)
    this

  renderWaiting: =>
    $actions = @$('.battle_actions')
    $actions.find('.move.button').popover('destroy')
    $actions.html """<div class="well well-battle-actions">
      Waiting for opponent...
      <a class="cancel">Cancel</a>
    </div>"""

  renderUserInfo: =>
    locals =
      yourTeam     : @model.getTeam()
      opponentTeam : @model.getOpponentTeam()
      numActive    : @model.numActive
      yourIndex    : @model.get('index')
      window       : window
    $userInfo = @$('.battle_user_info')
    $userInfo.find('.pokemon_icon').popover('destroy')
    $userInfo.html @user_info_template(locals)
    $userInfo.find('.pokemon_icon').each (i, el) =>
      $this = $(el)
      team = $this.data('team')
      slot = $this.data('slot')
      pokemon = @model.getPokemon(team, slot)
      #@pokemonPopover($this, pokemon)
    @renderTimers()
    this

  movePopover: ($this, moveName, move) =>
    {type, damage} = move
    damageFriendly = move.damage[0].toUpperCase() + move.damage.substr(1)
    targetFriendly = move.target[0].toUpperCase() + move.target.substr(1)
    displayName = []
    displayName.push(moveName)
    displayName.push("""<img src="#{TypeSprite(type)}" alt="#{type}"/>
      <img src="#{CategorySprite(move.damage)}" alt="#{damageFriendly}"/>
      <img src="#{TargetSprite(move)}" alt="#{targetFriendly}"/>""")
    options =
      title: displayName.join('<br>')
      html: true
      content: JST['move_hover_info']({window, move})
      trigger: 'hover'
      animation: false
      placement: 'top'
      container: 'body'
    $this.popover(options)

  pokemonPopover: ($this, pokemon) =>
    if @isIllusioned(pokemon)
      pokemon = pokemon.getTeam().attributes.pokemon.at(pokemon.getTeam().attributes.pokemon.length - 1)

    displayName = pokemon.get('species')
    displayName += " @ #{pokemon.get('item')}"  if pokemon.has('item')
    displayName += "<br>"
    for type in pokemon.getForme().types
      displayName += """<img src="#{TypeSprite(type)}" alt="#{type}"/>"""
    options =
      title: displayName
      html: true
      content: JST['battle_hover_info']({window, pokemon})
      trigger: 'hover'
      animation: false
      container: 'body'
    $this.popover(options)

  renderTeamPreview: =>
    locals =
      battle       : @model
      window       : window
    @$('.battle_container').append @team_preview_template(locals)

  togglePokemonOrSwitch: (e) =>
    $currentTarget = $(e.currentTarget)
    $activePokemon = @$('.arrange_pokemon.active')
    if $currentTarget.is('.active')
      $activePokemon.removeClass('active')
    else if $activePokemon.length > 0
      $activePokemon.removeClass('active')
      @swapElements($currentTarget.get(0), $activePokemon.get(0))
    else
      $currentTarget.addClass('active')

  swapElements: (element1, element2) ->
    [parent1, next1] = [element1.parentNode, element1.nextSibling]
    [parent2, next2] = [element2.parentNode, element2.nextSibling]

    parent1.insertBefore(element2, next1)
    parent2.insertBefore(element1, next2)

  submitTeamPreview: (e) =>
    $currentTarget = $(e.currentTarget)
    return  if $currentTarget.hasClass('disabled')
    $currentTarget.addClass('disabled')
    $teamPreview = @$('.battle_teams')
    indices = for element in @$('.arrange_team .pokemon_icon')
      $(element).data('index')
    @model.arrangeTeam(indices)
    $teamPreview.transition(opacity: 0, 250, => @removeTeamPreview())

  removeTeamPreview: =>
    $teamPreview = @$('.battle_teams')
    $teamPreview.remove()

  floatPercent: (player, slot, percent) =>
    return  if @skip?
    kind = (if percent >= 0 then "" else "red")
    percentText = "#{percent}"
    percentText = "+#{percentText}"  if percent >= 0
    percentText += "%"
    @floatText(player, slot, percentText, kind)

  floatText: (player, slot, text, kind = "") =>
    return  if @skip?
    $sprite = @$sprite(player, slot)
    [x, y] = @getPokemonPosition(player, slot)
    $text = $('<span/>').addClass("percentage #{kind}").text(text)
    $text.hide().appendTo(@$('.battle_pane'))
    x -= $text.width() / 2
    y -= 20
    $text.css(position: 'absolute', top: y, left: x).show()
    if kind == 'red'
      $text.transition(top: "+=30", 1000, 'easeOutCubic')
      $text.delay(1000)
      $text.transition(opacity: 0, 1000, -> $text.remove())
    else
      $text.transition(top: "-=30", 1000, 'easeOutCubic')
      $text.delay(1000)
      $text.transition(opacity: 0, 1000, -> $text.remove())

  switchIn: (player, slot, fromSlot, done) =>
    $oldPokemon = @$pokemon(player, slot)
    $newPokemon = @$pokemon(player, fromSlot)
    $newSprite = @$sprite(player, fromSlot)
    pokemon = @model.getPokemon(player, slot)
    @renderUserInfo()

    # Prepare old/new pokemon
    $oldPokemon.attr('data-slot', fromSlot)
    $newPokemon.attr('data-slot', slot)
    $newPokemon.removeClass('hidden')
    @pokemonPopover($newSprite, pokemon)
    
    pokemon.set('beeninbattle', true)

    @cannedText('SENT_OUT', player, player, slot)

    if @skip?
      $oldPokemon.css(opacity: 0)
      $newPokemon.css(opacity: 1)
      done()
      return

    # Create and position pokeball
    [x, y] = @getPokemonPosition(player, slot)
    $pokeball = @makePokeball(x, y)
    $pokeball.css(opacity: 0)
    $pokeball.appendTo(@$(".battle_pane"))

    # Start animations
    $oldPokemon.css(opacity: 0)
    $newPokemon.css(opacity: 0)
    $pokeball.css(opacity: 1)
    releasePokemon = =>
      $pokeball.css(opacity: 0)
      $newSprite
        .transition(y: -15, scale: .1, 0)
        .transition(scale: 1, 250 * @speed)
        .transition y: 0, 250 * @speed, 'out', =>
          @removePokeball($pokeball)
      setTimeout(done, 500 * @speed)
      $newPokemon.transition(opacity: 1)
    setTimeout(releasePokemon, 250 * @speed)

  switchOut: (player, slot, done) =>
    $pokemon = @$pokemon(player, slot)
    $sprite = @$sprite(player, slot)
    @cannedText('WITHDREW', player, player, slot)

    if @skip?
      $pokemon.addClass('hidden')
      $sprite.popover('destroy')
      done()
      return

    width = $sprite.width()
    height = $sprite.height()
    $sprite.transition(scale: 0.1, x: width >> 1, y: height, 150 * @speed)
    $pokemon.transition opacity: 0, 250 * @speed, ->
      $pokemon.addClass('hidden').css(opacity: 1)
      $sprite.popover('destroy')
      $sprite.transition(scale: 1, x: 0, y: 0, 0)
    setTimeout(done, 250 * @speed)

  makePokeball: (x, y) =>
    $pokeball = $("""<div class="pokeball"/>""")
    $pokeball.css(top: y, left: x)
    size = 22
    $pokeball.width(size).height(size)
    func = ->
      $pokeball.css(backgroundPositionY: -10 - func.counter * 40)
      func.counter = (func.counter + 1) % 8
    func.counter = 1
    id = setInterval(func, 40)
    $pokeball.data('animation-id', id)
    $pokeball

  removePokeball: ($pokeball) =>
    id = $pokeball.data('animation-id')
    clearTimeout(id)
    $pokeball.remove()

  logMove: (player, slot, moveName, done) =>
    owner = @model.getTeam(player).escape('owner')
    pokemon = @model.getPokemon(player, slot)
    @addMoveMessage(owner, pokemon, moveName)
    @lastMove = moveName
    done()

  moveSuccess: (player, slot, targetSlots, moveName, done) =>
    return done()  if @skip?

    gen = @model.get('generation').toUpperCase()
    moveData = window.Generations[gen]?.MoveData[moveName]
    if !moveData
      console.error("Could not display animation for #{moveName} as it does not
        exist in #{gen}.")
      done()
      return

    [targetPlayer, targetSlot] = targetSlots[0]
    $attacker = @$sprite(player, slot)
    $defender = @$sprite(targetPlayer, targetSlot)
    [ax, ay] = @getPokemonPosition(player, slot)
    [dx, dy] = @getPokemonPosition(targetPlayer, targetSlot)
    front = @isFront(player)
    scale = (if front then 1.3 else 1/1.3)
    if moveName == 'Earthquake'
      speed = @speed
      $attacker.add($defender).each (index) ->
        $(this).transition(x: -75, 62.5 * speed, 'easeInOutCubic')
          .transition(x: 75, 125 * speed, 'easeInOutCubic')
          .transition(x: -30, 125 * speed, 'easeInOutCubic')
          .transition(x: 30, 125 * speed, 'easeInOutCubic')
          .transition(x: 0, 62.5 * speed, 'easeInOutCubic')
      setTimeout(done, 500 * @speed)
    else if 'contact' in moveData.flags
      # Simple attack animation
      # Tackling the opponent
      $attacker
        .transition(x: dx - ax, y: dy - ay, scale: scale, 250 * @speed, 'in')
        .transition(x: 0, y: 0, scale: 1, 250 * @speed, 'out')
      $defender.delay(400 * @speed)
        .transition(x: (if front then -16 else 8), 50 * @speed, 'easeOutCubic')
        .transition(x: 0, 50 * @speed, 'easeInOutCubic')
      setTimeout(done, 500 * @speed)
    else if moveData['power'] > 0
      # Non-contact attacking move
      # Projectile
      $projectile = @$projectile(player, slot, moveData)
      [transX, transY] = [(dx - ax), (dy - ay)]
      $projectile
        .transition(x: transX / 2, y: transY / 2, scale: (scale + 1) / 2, 200 * @speed, 'easeOutCubic')
        .transition(x: transX, y: transY, scale: scale, 200 * @speed, 'easeOutCubic')
        .transition(opacity: 0, 100 * @speed, -> $projectile.remove())
      $defender.delay(400 * @speed)
        .transition(x: -4, 0, 'linear').delay(50 * @speed)
        .transition(x: 4, 0, 'linear').delay(50 * @speed)
        .transition(x: 0, 0, 'linear')
      setTimeout(done, 500 * @speed)
    else if player != targetPlayer || slot != targetSlot
      # This is a non-attacking move that affects another pokemon
      # S-shaped movement
      $projectile = @$projectile(player, slot, moveData)
      [transX, transY] = [(dx - ax), (dy - ay)]
      $projectile
        .transition(x: transX * 2 / 3, y: transY / 3, 150 * @speed, 'easeInOutSine')
        .transition(x: transX / 3, y: transY * 2 / 3, 100 * @speed, 'easeInOutSine')
        .transition(x: transX, y: transY, 150 * @speed, 'easeInOutSine')
        .transition opacity: 0, 100 * @speed, 'easeInOutSine', ->
          $projectile.remove()
      setTimeout(done, 500 * @speed)
    else
      # Side-to-side movement
      $attacker = @$sprite(player, slot)
      $attacker
        .transition(x: -16, 125 * @speed, 'easeInOutSine')
        .transition(x: 16, 250 * @speed, 'easeInOutSine')
        .transition(x: 0, 125 * @speed, 'easeInOutSine')
      setTimeout(done, 500 * @speed)

  cannedText: (cannedString, args...) =>
    @parseCannedText(CannedText[cannedString], args, ->)

  parseCannedText: (cannedInteger, args, done) =>
    cannedTextName = CannedMapReverse[cannedInteger]
    cannedText = @getCannedText(cannedTextName, args)
    @addLog(cannedText)
    @actOnCannedText(cannedTextName, cannedText, done)

  # Some canned text requires special actions.
  # For example, misses require a delay, and also prints to the battle pane.
  actOnCannedText: (cannedTextName, cannedText, done) =>
    return done()  if @skip?
    switch cannedTextName
      when 'MOVE_MISS', 'JUMP_KICK_MISS', 'MOVE_FAIL', 'IMMUNITY'
        @addSummary(cannedText)
        setTimeout(done, 500 * @speed)
      when 'PARALYZE_CONTINUE', 'FREEZE_CONTINUE', 'SLEEP_CONTINUE',\
            'SUN_END', 'RAIN_END', 'SAND_END', 'HAIL_END',\
            'SAND_CONTINUE', 'HAIL_CONTINUE'
        @addSummary(cannedText, newline: true)
        done()
      else
        @addSummary(cannedText)
        done()

  getCannedText: (cannedTextName, args) =>
    cannedText = 'Please refresh to see this text!'
    genIndex   = ALL_GENERATIONS.indexOf(@model.get('generation'))
    language   = 'en'
    # Run through inheritance chain of generations to find the canned text
    for i in [genIndex..0] by -1
      generation = ALL_GENERATIONS[i]
      if CannedMap[generation]?[language]?[cannedTextName]
        cannedText = CannedMap[generation][language][cannedTextName]
        break
    # Replace special characters in the canned text with the arguments
    cannedText.replace /\$([a-z]+|\d+)/g, (match, p1, index) =>
      switch p1
        when 'p'
          [player, slot] = args.splice(0, 2)
          pokemon = @model.getPokemon(player, slot)
          if @isIllusioned(pokemon)
            pokemon = pokemon.getTeam().attributes.pokemon.at(pokemon.getTeam().attributes.pokemon.length - 1)
          pokemon.escape('name')
        when 't'
          [player] = args.splice(0, 1)
          @model.getTeam(player).escape('owner')
        when 'ts'
          [player] = args.splice(0, 1)
          text = if @isFront(player)
            "the opposing team"
          else
            "your team"

          # Capitalize the text if necessary
          text = "#{text[0].toUpperCase()}#{text[1...]}"  if index == 0
          text
        else
          [text] = args.splice(0, 1)
          text

  activateAbility: (player, slot, abilityName, done) =>
    return done()  if @skip?

    pokemon = @model.getPokemon(player, slot)
    isFront = @isFront(player)
    $ability = $('<div/>').addClass('ability_activation')
    $ability.html("#{pokemon.escape('name')}'s <strong>#{abilityName}</strong>")
    $ability.addClass((if isFront then 'front' else 'back'))
    $ability.width(1)
    $ability.appendTo(@$('.battle_pane'))
    $ability
      .transition(opacity: 1, width: 150, 100 * @speed, 'easeInQuad')
      .delay(3000)
      .transition opacity: 0, 300 * @speed, 'easeInQuad', ->
        $ability.remove()
    setTimeout(done, 500 * @speed)

  changeSprite: (player, slot, species, forme, done) =>
    $spriteContainer = @$spriteContainer(player, slot)
    $sprite = @$sprite(player, slot)
    $spriteContainer.data('species', species)
    $spriteContainer.data('forme', forme)

    if @skip?
      @renderPokemon $spriteContainer, ->
        $sprite.popover('destroy')
        $sprite.remove()
      done()
      return

    $sprite.fadeOut 200 * @speed, =>
      @renderPokemon $spriteContainer, ($image) ->
        $sprite.popover('destroy')
        $sprite.remove()
        $image.hide().fadeIn(200 * @speed)

    # Don't waste time changing the sprite if we can't see it.
    if @model.getPokemon(player, slot).isFainted()
      done()
    else
      setTimeout(done, 400 * @speed)

  changeName: (player, slot, newName, done) =>
    nameBox = @$pokemon(player, slot).find('.pokemon-name')
    nameBox.html newName
    done()

  changeWeather: (newWeather, done) =>
    $overlays = @$('.battle_overlays')
    $overlays.find('.weather').transition(opacity: 0, 500 * @speed, -> $(this).remove())
    [overlayWidth, overlayHeight] = [600, 300]
    $weather = switch newWeather
      when Weather.RAIN
        $weather = $("<div/>").addClass("battle_overlay weather rain")
        for i in [0...100]
          dropLeft = _.random(-300, overlayWidth)
          dropTop = _.random(-2 * overlayHeight - 100, overlayHeight)

          $drop = $('<div class="drop"></div>')
          $drop.css(left: dropLeft, top: dropTop)
          $weather.append($drop)
        $overlays.append($weather)
        $weather
      when Weather.SUN
        $weather = $("<div/>").addClass("battle_overlay weather sun")
        for i in [0...10]
          millisecs = Math.floor(Math.random() * 3000) + 'ms'
          $ray = $('<div class="ray"></div>')
          $ray.css(left: Math.floor(Math.random() * overlayWidth))
          $ray.css({
            '-webkit-animation-delay': millisecs
            '-moz-animation-delay': millisecs
            '-ms-animation-delay': millisecs
            '-o-animation-delay': millisecs
            'animation-delay': millisecs
          })
          $weather.append($ray)
        $overlays.append($weather)
        $weather
      when Weather.SAND
        $weather = $("<div/>").addClass("battle_overlay weather sand")
        [width, height] = [overlayWidth, overlayHeight]
        [sandWidth, sandHeight] = [600, 600]
        streams = []
        for x in [-(2 * width)..width] by sandWidth
          for y in [-(2 * height)...height] by sandHeight
            percentX = Math.floor(100 * x / width) + "%"
            percentY = Math.floor(100 * y / height) + "%"
            streams.push([percentX, percentY])
        for [left, top] in streams
          $sand = $('<div class="sand_overlay"/>')
          $sand.css({left, top})
          $weather.append($sand)
        $overlays.append($weather)
        $weather
      when Weather.HAIL
        $weather = $("<div/>").addClass("battle_overlay weather hail")
        for i in [0...100]
          hailstoneLeft = _.random(-300, overlayWidth)
          hailstoneTop = _.random(-2 * overlayHeight, overlayHeight)

          $hailstone = $('<div class="hailstone"></div>')
          size = Math.floor(Math.random() * 5) + 5
          $hailstone.width(size)
          $hailstone.height(size)
          $hailstone.css(left: hailstoneLeft, top: hailstoneTop)
          $weather.append($hailstone)
        $overlays.append($weather)
        $weather
      else $()
    $weather.transition(opacity: 1, 500 * @speed)
    done()

  attachPokemon: (player, slot, attachment, done) =>
    pokemon = @model.getPokemon(player, slot)
    $pokemon = @$pokemon(player, slot)
    switch attachment
      when 'SubstituteAttachment'
        $spriteContainer = @$spriteContainer(player, slot)
        $spriteContainer.addClass('fade')
        substituteUrl = (if @isFront(player) then "substitute" else "subback")
        substituteUrl = "../Sprites/battle/#{substituteUrl}.gif"
        @addPokemonImage $pokemon, substituteUrl, callback: ($image) =>
          [x, y] = @getPokemonPosition(player, slot)
          $image.addClass('substitute')
          width = $image.width()
          height = $image.height()
          x -= (width >> 1)
          y -= (height >> 1)
          yOffset = 200
          $image.css(position: 'absolute', left: x, top: y)
          $image.show()
          return done()  if @skip?
          setTimeout ->
            $image
              .transition(y: -yOffset, 0)
              .transition(y: 0, 200 * @speed, 'easeInQuad')
              .transition(y: -yOffset >> 3, 100 * @speed, 'easeOutQuad')
              .transition(y: 0, 100 * @speed, 'easeInQuad')
          , 0
          setTimeout(done, 500 * @speed)
      when 'ConfusionAttachment'
        @addPokemonEffect($pokemon, "confusion", "Confusion")
        @addLog("#{pokemon.escape('name')} became confused!")
        done()
      when 'ProtectAttachment', 'KingsShieldAttachment', 'SpikyShieldAttachment'
        @cannedText('PROTECT_CONTINUE', player, slot)
        @attachScreen(player, slot, 'pink', 0, done)
      when 'Air Balloon'
        @addPokemonEffect($pokemon, "balloon", "Balloon")
        @addLog("#{pokemon.escape('name')} floats in the air with its Air Balloon!")
        done()
      when 'Paralyze'
        pokemon.set('status', 'paralyze')
        done()
      when 'Burn'
        pokemon.set('status', 'burn')
        done()
      when 'Poison'
        pokemon.set('status', 'poison')
        done()
      when 'Toxic'
        pokemon.set('status', 'toxic')
        done()
      when 'Freeze'
        pokemon.set('status', 'freeze')
        done()
      when 'Sleep'
        pokemon.set('status', 'sleep')
        done()
      else
        done()

  attachTeam: (player, attachment, done) =>
    $battlePane = @$('.battle_pane')
    isFront = @isFront(player)
    switch attachment
      when "StealthRockAttachment"
        $div = $("<div/>").addClass("field-#{player} team-stealth-rock")
        if isFront
          [ oldX, oldY ] = [ "20%", "80%" ]
          [ newX, newY ] = [ "67%", "45%" ]
        else
          [ oldX, oldY ] = [ "80%", "20%" ]
          [ newX, newY ] = [ "34%", "81%" ]
        if @skip?
          $div.css(top: newY, left: newX, opacity: .5)
          $battlePane.prepend($div)
          done()
        else
          $div.css(top: oldY, left: oldX, opacity: 0)
          $div.transition(top: newY, left: newX, opacity: 1, 500 * @speed)
            .delay(1000 * @speed).transition(opacity: .5)
          $battlePane.prepend($div)
          setTimeout(done, 500 * @speed)
      when "ToxicSpikesAttachment"
        $div = $("<div/>").addClass("field-#{player} team-toxic-spikes")
        previousLayers = @$(".field-#{player}.team-toxic-spikes").length
        if isFront
          oldY = "80%"
          oldX = "20%"
          newY = switch previousLayers
            when 0 then "51%"
            when 1 then "50%"
          newX = switch previousLayers
            when 0 then "77%"
            when 1 then "73%"
        else
          oldY = "30%"
          oldX = "80%"
          newY = switch previousLayers
            when 0 then "87%"
            when 1 then "86%"
          newX = switch previousLayers
            when 0 then "23%"
            when 1 then "27%"
        if @skip?
          $div.css(top: newY, left: newX, opacity: .5)
          $battlePane.prepend($div)
          done()
        else
          $div.css(top: oldY, left: oldX, opacity: 0)
          $div.transition(top: newY, left: newX, opacity: 1, 500 * @speed)
            .delay(1000 * @speed).transition(opacity: .5)
          $battlePane.prepend($div)
          setTimeout(done, 500 * @speed)
      when "SpikesAttachment"
        $div = $("<div/>").addClass("field-#{player} team-spikes")
        previousLayers = @$(".field-#{player}.team-spikes").length
        if isFront
          oldY = "80%"
          oldX = "20%"
          newY = switch previousLayers
            when 0 then "49%"
            when 1 then "52%"
            when 2 then "50%"
          newX = switch previousLayers
            when 0 then "87%"
            when 1 then "84%"
            when 2 then "82%"
        else
          oldY = "30%"
          oldX = "80%"
          newY = switch previousLayers
            when 0 then "85%"
            when 1 then "88%"
            when 2 then "86%"
          newX = switch previousLayers
            when 0 then "13%"
            when 1 then "16%"
            when 2 then "18%"
        if @skip?
          $div.css(top: newY, left: newX, opacity: .5)
          $battlePane.prepend($div)
          done()
        else
          $div.css(top: oldY, left: oldX, opacity: 0)
          $div.transition(top: newY, left: newX, opacity: 1, 500 * @speed)
            .delay(1000 * @speed).transition(opacity: .5)
          $battlePane.prepend($div)
          setTimeout(done, 500 * @speed)
      when "StickyWebAttachment"
        $div = $("<div/>").addClass("field-#{player} team-sticky-web")
        if isFront
          [ oldX, oldY ] = [ "0%",  "50%" ]
          [ newX, newY ] = [ "65%", "10%"  ]
        else
          [ oldX, oldY ] = [ "65%", "10%"  ]
          [ newX, newY ] = [ "0%",  "50%" ]
        if @skip?
          $div.css(top: newY, left: newX, opacity: .5)
          $battlePane.prepend($div)
          done()
        else
          $div.css(top: oldY, left: oldX, opacity: 0)
          $div.animate(top: newY, left: newX, opacity: 1, 1000 * @speed, 'easeOutElastic')
            .delay(1000 * @speed).animate(opacity: .2)
          $battlePane.prepend($div)
          setTimeout(done, 500 * @speed)
      when "ReflectAttachment"
        @cannedText('REFLECT_START', player)
        @attachScreen(player, 'blue', 10, done)
      when "LightScreenAttachment"
        @cannedText('LIGHT_SCREEN_START', player)
        @attachScreen(player, 'yellow', 5, done)
      else
        done()

  attachBattle: (attachment, done) =>
    done()

  attachScreen: (player, slot, klass, offset, done=->) =>
    if arguments.length == 4
      [slot, klass, offset, done] = [null, slot, klass, offset]
    finalSize = 100
    halfSize = (finalSize >> 1)
    $screen = $("<div/>").addClass("team-screen #{klass} field-#{player}")
    $screen.addClass("slot-#{slot}")  if slot
    [x, y] = @getPokemonPosition(player, 0)
    x += offset
    y += offset
    $screen.css(left: x, top: y).appendTo(@$('.battle_pane'))
    if @skip?
      $screen.css(width: finalSize, height: finalSize)
      $screen.css(x: -halfSize, y: -halfSize)
      done()
    else
      $screen
        .transition(width: finalSize, x: -halfSize, 250 * @speed, 'easeInOutCubic')
        .transition(height: finalSize, y: -halfSize, 250 * @speed, 'easeInOutCubic')
      setTimeout(done, 500 * @speed)

  unattachScreen: (player, slot, klass, done=->) =>
    if arguments.length == 3
      [slot, klass, done] = [null, slot, klass]
    selector = ".team-screen.#{klass}.field-#{player}"
    selector += ".slot-#{slot}"  if slot
    $selector = @$(selector)
    $selector.fadeOut(500 * @speed, -> $selector.remove())
    done()

  boost: (player, slot, deltaBoosts, options = {}) =>
    pokemon = @model.getPokemon(player, slot)
    if @isIllusioned(pokemon)
      pokemonName = pokemon.getTeam().attributes.pokemon.at(pokemon.getTeam().attributes.pokemon.length - 1).attributes.name
    else
      pokemonName = pokemon.escape('name')
    stages = pokemon.get('stages')
    $pokemon = @$pokemon(player, slot)
    $effects = $pokemon.find('.pokemon-effects')
    posFloatText = []
    negFloatText = []
    for stat, delta of deltaBoosts
      previous = stages[stat]
      stages[stat] += delta
      # Boost log message
      unless options.silent
        message = @makeBoostMessage(pokemonName, stat, delta, stages[stat])
        @addLog(message)  if message

      # Boost in the view
      abbreviatedStat = switch stat
        when "attack" then "Att"
        when "defense" then "Def"
        when "speed" then "Spe"
        when "specialAttack" then "Sp.A"
        when "specialDefense" then "Sp.D"
        when "accuracy" then "Acc."
        when "evasion" then "Eva."
        else stat
      amount = stages[stat]
      amount = "+#{amount}"  if amount > 0
      finalStat = "#{amount} #{abbreviatedStat}"
      $effect = @addPokemonEffect($pokemon, "boost #{stat}", finalStat)
      if amount < 0
        $effect.addClass('negative')
        negFloatText.push("#{delta} #{abbreviatedStat}")
      else if amount > 0
        $effect.removeClass('negative')
        posFloatText.push("+#{delta} #{abbreviatedStat}")
      else # amount == 0
        $effect.remove()

    # Boost text messages
    if options.floatText
      if negFloatText.length > 0
        @floatText(player, slot, negFloatText.join('/'), 'red')
      if posFloatText.length > 0
        @floatText(player, slot, posFloatText.join('/'))
    true

  makeBoostMessage: (pokemonName, stat, amount, currentBoost) ->
    stat = switch stat
      when "attack" then "Attack"
      when "defense" then "Defense"
      when "speed" then "Speed"
      when "specialAttack" then "Special Attack"
      when "specialDefense" then "Special Defense"
      when "accuracy" then "Accuracy"
      when "evasion" then "Evasion"
      else stat
    if amount > 0
      if amount == 12
        "#{pokemonName} cut its own HP and maximized its #{stat}!"
      else
        adverb = ""              if amount == 1
        adverb = " sharply"      if amount == 2
        adverb = " drastically"  if amount >= 3
        "#{pokemonName}'s #{stat} rose#{adverb}!"
    else if amount < 0
      adverb = ""           if amount == -1
      adverb = " harshly"   if amount == -2
      adverb = " severely"  if amount <= -3
      "#{pokemonName}'s #{stat}#{adverb} fell!"
    else if currentBoost == 6
      "#{pokemonName}'s #{stat} won't go any higher!"
    else if currentBoost == -6
      "#{pokemonName}'s #{stat} won't go any lower!"

  unattachPokemon: (player, slot, effect, done) =>
    pokemon = @model.getPokemon(player, slot)
    $pokemon = @$pokemon(player, slot)
    switch effect
      when 'SubstituteAttachment'
        $spriteContainer = @$spriteContainer(player, slot)
        $spriteContainer.removeClass('fade')
        $substitute = $pokemon.find('.substitute').first()

        if @skip?
          $substitute.remove()
          done()
        else
          $substitute.transition y: 300, opacity: 0, 300 * @speed, ->
            $substitute.remove()
          setTimeout(done, 300 * @speed)
      when 'ProtectAttachment', 'KingsShieldAttachment', 'SpikyShieldAttachment'
        @unattachScreen(player, slot, 'pink', done)
      when 'Air Balloon'
        $pokemon.find(".pokemon-effect.balloon").remove()
        @addLog("#{pokemon.escape('name')}'s Air Balloon popped!")
        done()
      when 'ConfusionAttachment'
        $pokemon.find(".pokemon-effect.confusion").remove()
        done()
      when 'Paralyze'
        pokemon.set('status', null)
        done()
      when 'Burn'
        pokemon.set('status', null)
        done()
      when 'Poison'
        pokemon.set('status', null)
        done()
      when 'Toxic'
        pokemon.set('status', null)
        done()
      when 'Freeze'
        pokemon.set('status', null)
        done()
      when 'Sleep'
        pokemon.set('status', null)
        done()
      else
        done()

  setBoosts: (player, slot, boosts) =>
    pokemon = @model.getPokemon(player, slot)
    stages = pokemon.get('stages')
    for stat of boosts
      boosts[stat] -= stages[stat]
    @boost(player, slot, boosts, silent: true)

  resetBoosts: (player, slot) =>
    pokemon = @model.getPokemon(player, slot)
    pokemon.resetBoosts()
    $pokemon = @$pokemon(player, slot)
    $pokemon.find('.boost').remove()

  handlePercent: (pokemon) =>
    $pokemon = @$pokemon(pokemon)
    $info = $pokemon.find(".pokemon-info")
    $allHP = $info.find('.hp')
    $hpText = $info.find('.hp-text')
    percent = pokemon.getPercentHP()
    if percent <= 20
      $allHP.css(backgroundColor: "#f00")
    else if percent <= 50
      $allHP.css(backgroundColor: "#ff0")
    else
      $allHP.css(backgroundColor: "#0f0")
    $allHP.width("#{percent}%")
    $hpText.text("#{percent}%")
    deltaPercent = (percent - pokemon.previous('percent'))
    [player, slot] = [$pokemon.data('team'), $pokemon.data('slot')]
    @floatPercent(player, slot, deltaPercent)

  handleStatus: (pokemon, status) =>
    $pokemon = @$pokemon(pokemon)
    if status?
      $effects = $pokemon.find('.pokemon-effects')
      display = @mapStatusForDisplay(status)
      @addPokemonEffect($pokemon, status, display)
    else
      $pokemon.find(".pokemon-effect.#{pokemon.previous('status')}").remove()

  showSpinner: =>
    @$('.battle_actions .show_spinner').removeClass('hidden')

  mapStatusForDisplay: (status) =>
    switch status
      when "burn" then "BRN"
      when "paralyze" then "PAR"
      when "poison" then "PSN"
      when "toxic" then "TOX"
      when "freeze" then "FRZ"
      when "sleep" then "SLP"

  addPokemonEffect: ($pokemon, klass, text) =>
    $effects = $pokemon.find(".pokemon-effects")
    $effect = $effects.find(".pokemon-effect.#{klass.replace(/\s+/g, '.')}")
    return $effect  if !text
    if $effect.length == 0
      $effect = $("<div class='pokemon-effect #{klass}'>#{text}</div>")
      $effect.appendTo($effects)
    else
      $effect.text(text)
    $effect

  unattachTeam: (player, attachment, done) =>
    $battlePane = @$('.battle_pane')
    switch attachment
      when "StealthRockAttachment"
        $battlePane.find(".field-#{player}.team-stealth-rock").remove()
        done()
      when "ToxicSpikesAttachment"
        $battlePane.find(".field-#{player}.team-toxic-spikes").remove()
        done()
      when "SpikesAttachment"
        $battlePane.find(".field-#{player}.team-spikes").remove()
        done()
      when "StickyWebAttachment"
        $battlePane.find(".field-#{player}.team-sticky-web").remove()
        done()
      when 'ReflectAttachment'
        @cannedText('REFLECT_END', player)
        @unattachScreen(player, 'blue', done)
      when 'LightScreenAttachment'
        @cannedText('LIGHT_SCREEN_END', player)
        @unattachScreen(player, 'yellow', done)
      else
        done()

  unattachBattle: (effect, done) =>
    done()

  updateTimers: (timers) =>
    now = $.now()
    for timer, index in timers
      @timers[index] = timer
      @timerUpdatedAt[index] = now

  renderTimers: =>
    for i in [0..1]
      @renderTimer(i)

  countdownTimers: =>
    @renderTimers()
    diff = ($.now() - @battleStartTime - @timerIterations * 1000)
    @timerIterations++
    @countdownTimersId = setTimeout(@countdownTimers, 1000 - diff)

  renderTimer: (index) =>
    $info = @$playerInfo(index)
    $remainingTimer = $info.find('.remaining-timer')
    $frozenTimer = $info.find('.frozen-timer')
    timeRemaining = @timers[index] - $.now() + @timerUpdatedAt[index]

    if !timeRemaining && timeRemaining != 0  # Falsy, but not 0.
      $remainingTimer.addClass('hidden')
    else
      $remainingTimer.removeClass('hidden')
      $remainingTimer.text PokeBattle.humanizeTime(timeRemaining)

    # Change timer class
    if timeRemaining <= 1 * 60 * 1000
      $frozenTimer.addClass("battle-timer-low")
      $remainingTimer.addClass("battle-timer-low")
    else
      $frozenTimer.removeClass("battle-timer-low")
      $remainingTimer.removeClass("battle-timer-low")

    # Ensure frozen timer displays right
    if @timerFrozenAt[index]
      $frozenTimer.text PokeBattle.humanizeTime(@timerFrozenAt[index])
      $frozenTimer.removeClass('hidden')
      $remainingTimer.addClass('battle-timer-small')
      if @showSecondaryTimer
        $remainingTimer.removeClass('hidden')
      else
        $remainingTimer.addClass('hidden')
    else
      $frozenTimer.addClass('hidden')
      $remainingTimer.removeClass('battle-timer-small hidden')

  # There are two ways your timer can stop:
  # 1. When you have no actions and you're waiting. e.g. opponent used U-turn.
  # 2. When you select a move.
  # The two cases differ; only display a secondary timer in the 2nd case.
  pauseTimer: (index, timeSinceLastAction) =>
    now = $.now()
    @timerFrozenAt[index] = @timers[index] - (now - @timerUpdatedAt[index])

    # Update timerUpdatedAt, because it only knows about when the timers are
    # were updated locally.
    @timerUpdatedAt[index] -= timeSinceLastAction  if timeSinceLastAction

    @showSecondaryTimer = timeSinceLastAction?
    @renderTimer(index)

  resumeTimer: (index) =>
    delete @timerFrozenAt[index]
    @renderTimer(index)

  $playerInfo: (index) =>
    $userInfo = @$('.battle_user_info')
    if index == @model.get('index')
      return $userInfo.find('.left')
    else
      return $userInfo.find('.right')

  announceWinner: (player, done) =>
    owner = @model.getTeam(player).escape('owner')
    message = "#{owner} won!"
    @announceWin(message, done)

  announceForfeit: (player, done) =>
    owner = @model.getTeam(player).escape('owner')
    message = "#{owner} has forfeited!"
    @announceWin(message, done)

  announceTimer: (player, done) =>
    owner = @model.getTeam(player).escape('owner')
    message = "#{owner} was given the timer win!"
    @announceWin(message, done)

  announceExpiration: (done) =>
    message = "The battle expired!"
    @announceWin(message, done)

  announceWin: (message, done) =>
    @chatView.print("<h3>#{message}</h3>")
    @addSummary(message, newline: true)
    @model.set('finished', true)
    done()

  handleEnd: (battle, end) =>
    if @shouldRenderEnd()
      @disableButtons()
      @$('.battle_actions').html(@battle_end_template({window}))
    clearTimeout(@countdownTimersId)

  handleRemoval: (battle) =>
    if battle == @model
      @remove()

  shouldRenderEnd: =>
    PokeBattle.primus?

  saveReplay: (e) =>
    $replayButton = $(e.currentTarget)
    return  if $replayButton.is('.disabled')
    $replayButton.addClass('disabled')
    $replayButton.find('.show_spinner').removeClass('hidden')
    PokeBattle.primus.send 'saveReplay', @model.id, (error, replayId) =>
      $replayButton.find('.show_spinner').addClass('hidden')
      if error
        @chatView.announce("error", error)
      else
        relativeUrl = "/replays/#{replayId}"
        absoluteUrl = "#{window.location.protocol}//#{window.location.host}"
        absoluteUrl += relativeUrl
        @chatView.announce("success", "Your replay was saved! Share the link: #{absoluteUrl}.")

  saveLog: =>
    log = []
    $children = @$('.messages').children()
    $children.each ->
      $this = $(this)
      isHeader = /H\d/i.test(@tagName)
      log.push ""  if isHeader
      log.push $this.text()
      log.push ""  if isHeader
    log = [ log.join('\n') ]
    fileName = (@model.get('teams').map((team) -> team.escape('owner'))).join(" vs ")
    fileName += ".txt"
    blob = new Blob(log, type: "text/plain;charset=utf-8", endings: "native")
    saveAs(blob, fileName)

  returnToLobby: =>
    PokeBattle.navigation.focusLobby()

  changeBattleSpeed: (e) =>
    @speed = Number($(e.currentTarget).val()) || 1
    try
      window.localStorage.setItem('battle_speed', @speed)
    catch

  $pokemon: (player, slot) =>
    if arguments.length == 1
      pokemon = player
      @model.get('teams').forEach (team, playerIndex) ->
        index = team.indexOf(pokemon)
        if index != -1
          player = playerIndex
          slot = index
          return
    @$(".pokemon[data-team='#{player}'][data-slot='#{slot}']")

  $spriteContainer: (player, slot) =>
    @$pokemon(player, slot).find('.sprite')

  $sprite: (player, slot) =>
    @$spriteContainer(player, slot).find('img')

  $projectile: (player, slot, moveData) =>
    $projectile = $('<div/>').addClass('projectile')
    $projectile.addClass(moveData['type'].toLowerCase())
    $projectile.appendTo(@$(".battle_pane"))
    [x, y] = @getPokemonPosition(player, slot)
    $projectile.css(left: x, top: y)
    $projectile

  isFront: (player) =>
    @model.get('index') != player

  faint: (player, slot, done) =>
    $pokemon = @$pokemon(player, slot)
    $sprite = @$sprite(player, slot)

    if @skip?
      $sprite.popover('destroy')
      $sprite.remove()
      done()
      return

    $sprite.transition y: 100, opacity: 0, 250 * @speed, 'ease-in', ->
      $sprite.popover('destroy')
      $sprite.remove()
    setTimeout(done, 250 * @speed)
    @renderUserInfo()

  resetPopovers: =>
    return  if !@model.teams
    for player in [0...2]
      for slot in [0...@model.numActive]
        $pokemon = @$pokemon(player, slot)
        pokemon = @model.getPokemon(player, slot)
        $sprite = @$sprite(player, slot)
        $sprite.popover('destroy')
        @pokemonPopover($sprite, pokemon)

  enableButtons: (validActions) =>
    if validActions
      @renderActions(validActions)
      @resumeTimer(@model.get('index'))
    else
      # We didn't get any actions; we must be already waiting.
      @disableButtons()

  disableButtons: =>
    @$('.battle_actions .switch.button').popover('destroy')
    @renderWaiting()

  addMoveMessage: (owner, pokemon, moveName) =>
    if @isIllusioned(pokemon)
      lastpokemon = pokemon.getTeam().attributes.pokemon.at(pokemon.getTeam().attributes.pokemon.length - 1)
      pokemon = lastpokemon
    @chatView.print("<p class='move_message'>#{owner}'s #{@pokemonHtml(pokemon)} used <strong>#{moveName}</strong>!</p>")
    @addSummary("#{owner}'s #{pokemon.escape('name')} used <strong>#{moveName}</strong>!", newline: true, big: true)

  isIllusioned: (pokemon) =>
    illusionmons = ['Zoroark', 'Zorua']
    return true if (pokemon.attributes.species in illusionmons) and pokemon.attributes.percent == 100 and @model.attributes.turn <= 1
    return true if pokemon.getIllu()
    return false

  addLog: (message) =>
    @chatView.print("<p>#{message}</p>")

  addSummary: (message, options = {}) =>
    return  if @skip?
    $summary = @$('.battle_summary')
    $summary.show()
    $p = $summary.children().last()
    if $p.length == 0 || $p.is('.newline') || options.newline
      $p = $("<p/>").html(message).hide()
      $p.addClass('newline')  if options.newline
      $p.addClass('big')  if options.big
      $p.appendTo($summary)
    else
      html = $p.html()
      $p.html("#{html} #{message}")
    $p.slideDown(200)
    # Remove the summaries over time if we can see the full log.
    return  unless @chatView.$el.is(':visible')
    removeP = ->
      $p.slideUp 200, ->
        $p.remove()
        $summary.hide()  if $summary.is(':empty')
    setTimeout(removeP, 4000)

  beginTurn: (turn, done) =>
    @chatView.print("<h2>Turn #{turn}</h2>")
    @model.set('turn', turn)
    done()

  continueTurn: (done) =>
    @$('.battle_summary').empty().hide()
    offset = @$('.battle_pane').offset().top + @$el.scrollTop()
    offset -= @$el.offset().top
    @$el.scrollTop(offset)
    done()

  makeMove: (e) =>
    forSlot = 0
    $target = $(e.currentTarget)
    moveName = $target.data('move-id')
    if $target.hasClass('disabled')
      console.log "Cannot use #{moveName}."
      return
    console.log "Making move #{moveName}"
    pokemon = @model.getPokemon(@model.get('index'), 0)
    @showSpinner()
    @model.makeMove(moveName, forSlot, @afterSelection.bind(this, pokemon))

  switchPokemon: (e) =>
    forSlot = 0
    $target = $(e.currentTarget)
    toSlot = $target.data('slot')
    if $target.hasClass('disabled')
      console.log "Cannot switch to #{toSlot}."
      return
    console.log "Switching to #{toSlot}"
    toSlot = parseInt(toSlot, 10)
    pokemon = @model.getPokemon(@model.get('index'), 0)
    @showSpinner()
    @model.makeSwitch(toSlot, forSlot, @afterSelection.bind(this, pokemon))

  cancelAction: (e) =>
    @$('.battle_actions').html """
    <div class="well well-battle-actions">Canceling...</div>
    """

    pokemon = @model.getPokemon(@model.get('index'), 0)
    @model.makeCancel()
    @afterAction(pokemon)

  megaEvolve: (e) =>
    $target = $(e.currentTarget)
    $target.toggleClass('pressed')
    pokemon = @model.getPokemon(@model.get('index'), 0)
    pokemon.set('megaEvolve', $target.hasClass("pressed"))

  afterSelection: (pokemon) =>
    @disableButtons()
    @pauseTimer(@model.get('index'), 0)
    @afterAction(pokemon)

  afterAction: (pokemon) =>
    pokemon.set('megaEvolve', false)

  preloadImages: =>
    gen   = window.Generations[@model.get('generation').toUpperCase()]
    teams = @model.get('teams').map (team, playerIndex) =>
      front = @isFront(playerIndex)
      team.get('pokemon').map (pokemon) ->
        species = pokemon.get('species')
        forme   = pokemon.get('forme')
        shiny   = pokemon.get('shiny')
        {id}    = gen.SpeciesData[species]
        formes  = gen.FormeData[species]
        formeNames = _.keys(formes)
        formeNames = _.filter formeNames, (formeName) ->
          forme == formeName || formes[formeName].isBattleOnly
        for formeName in formeNames
          PokemonSprite(id, formeName, front: front, shiny: shiny)
    # First pokemon of each team is loaded first, then second, etc.
    pokemonUrls = _.flatten(_.zip(teams...))
    for pokemonUrl in pokemonUrls
      image = new Image()
      image.src = pokemonUrl

  addPokemonImage: ($div, url, options = {}) =>
    scale = options.scale || 1
    image = new Image()
    $image = $(image)
    $image.load =>
      {width, height} = image
      if scale != 1
        width  *= scale
        height *= scale
        $image.width(width)
        $image.height(height)
      options.callback?($image)
    image.src = url
    $image.hide().appendTo($div)

  getPokemonPosition: (player, slot) =>
    if player == @model.get('index')
      [96, 208]
    else
      [332, 108]

  remove: =>
    clearTimeout(@countdownTimersId)
    super()

  pokemonHtml: (pokemon) =>
    "<a class='pokemon-link' href='#{pokemon.getPokedexUrl()}'
      target='_blank'>#{pokemon.escape('name')}</a>"

  setVisibleTeam: =>
    battle = @model
    battle.set('visibleteam', true)