RootView = require 'views/core/RootView'

GameUIState = require 'models/GameUIState'
God = require 'lib/God'
LevelLoader = require 'lib/LevelLoader'
GoalManager = require 'lib/world/GoalManager'
ScriptManager = require 'lib/scripts/ScriptManager'
Surface = require 'lib/surface/Surface'
ThangType = require 'models/ThangType'
Level = require 'models/Level'
LevelSession = require 'models/LevelSession'
State = require 'models/State'
utils = require 'core/utils'
urls = require 'core/urls'
Course = require 'models/Course'
GameDevVictoryModal = require './modal/GameDevVictoryModal'

TEAM = 'humans'

module.exports = class PlayGameDevLevelView extends RootView
  id: 'play-game-dev-level-view'
  template: require 'templates/play/level/play-game-dev-level-view'
  
  subscriptions:
    'god:new-world-created': 'onNewWorld'

  events:
    'click #play-btn': 'onClickPlayButton'
    'click #copy-url-btn': 'onClickCopyURLButton'
    'click #play-more-codecombat-btn': 'onClickPlayMoreCodeCombatButton'

  initialize: (@options, @levelID, @sessionID) ->
    @state = new State({
      loading: true
      progress: 0
      creatorString: ''
    })

    @supermodel.on 'update-progress', (progress) =>
      @state.set({progress: (progress*100).toFixed(1)+'%'})
    @level = new Level()
    @session = new LevelSession()
    @gameUIState = new GameUIState()
    @courseID = @getQueryVariable 'course'
    @god = new God({ @gameUIState, indefiniteLength: true })
    @levelLoader = new LevelLoader({ @supermodel, @levelID, @sessionID, observing: true, team: TEAM, @courseID })
    @supermodel.setMaxProgress 1 # Hack, why are we setting this to 0.2 in LevelLoader?
    @listenTo @state, 'change', _.debounce @renderAllButCanvas

    @levelLoader.loadWorldNecessities()

    .then (levelLoader) =>
      { @level, @session, @world } = levelLoader
      @god.setLevel(@level.serialize {@supermodel, @session})
      @god.setWorldClassMap(@world.classMap)
      @goalManager = new GoalManager(@world, @level.get('goals'), @team)
      @god.setGoalManager(@goalManager)
      @god.angelsShare.firstWorld = false # HACK
      me.team = TEAM
      @session.set 'team', TEAM
      @scriptManager = new ScriptManager({
        scripts: @world.scripts or [], view: @, @session, levelID: @level.get('slug')})
      @scriptManager.loadFromSession() # Should we? TODO: Figure out how scripts work for game dev levels
      @renderAllButCanvas()
      @supermodel.finishLoading()

    .then (supermodel) =>
      @levelLoader.destroy()
      @levelLoader = null
      webGLSurface = @$('canvas#webgl-surface')
      normalSurface = @$('canvas#normal-surface')
      @surface = new Surface(@world, normalSurface, webGLSurface, {
        thangTypes: @supermodel.getModels(ThangType)
        levelType: @level.get('type', true)
        @gameUIState
        resizeStrategy: 'wrapper-size'
      })
      @listenTo @surface, 'resize', @onSurfaceResize
      worldBounds = @world.getBounds()
      bounds = [{x: worldBounds.left, y: worldBounds.top}, {x: worldBounds.right, y: worldBounds.bottom}]
      @surface.camera.setBounds(bounds)
      @surface.camera.zoomTo({x: 0, y: 0}, 0.1, 0)
      @surface.setWorld(@world)
      @scriptManager.initializeCamera()
      @renderSelectors '#info-col'
      @spells = @session.generateSpellsObject level: @level
      goalNames = (utils.i18n(goal, 'name') for goal in @goalManager.goals)
      
      course = if @courseID then new Course({_id: @courseID}) else null
      shareURL = urls.playDevLevel({@level, @session, course})
      
      @state.set({
        loading: false
        goalNames
        shareURL
        creatorString: $.i18n.t('play_game_dev_level.created_by').replace('{{name}}', @session.get('creatorName'))
      })
      @eventProperties = {
        category: 'Play GameDev Level'
        @courseID
        sessionID: @session.id
        levelID: @level.id
        levelSlug: @level.get('slug')
      }
      window.tracker?.trackEvent 'Play GameDev Level - Load', @eventProperties, ['Mixpanel']
      @god.createWorld(@spells, false, false, true)

    .catch (e) =>
      throw e if e.stack
      @state.set('errorMessage', e.message)

  onClickPlayButton: ->
    @god.createWorld(@spells, false, true)
    Backbone.Mediator.publish('playback:real-time-playback-started', {})
    Backbone.Mediator.publish('level:set-playing', {playing: true})
    action = if @state.get('playing') then 'Play GameDev Level - Restart Level' else 'Play GameDev Level - Start Level'
    window.tracker?.trackEvent(action, @eventProperties, ['Mixpanel'])
    @state.set('playing', true)

  onClickCopyURLButton: ->
    @$('#copy-url-input').val(@state.get('shareURL')).select()
    @tryCopy()
    window.tracker?.trackEvent('Play GameDev Level - Copy URL', @eventProperties, ['Mixpanel'])

  onClickPlayMoreCodeCombatButton: ->
    window.tracker?.trackEvent('Play GameDev Level - Click Play More CodeCombat', @eventProperties, ['Mixpanel'])
    
  onSurfaceResize: ({height}) ->
    @state.set('surfaceHeight', height)
    
  renderAllButCanvas: ->
    @renderSelectors('#info-col', '#share-row')
    height = @state.get('surfaceHeight')
    if height
      @$el.find('#info-col').css('height', @state.get('surfaceHeight'))

  onNewWorld: (e) ->
    if @goalManager.checkOverallStatus() is 'success'
      modal = new GameDevVictoryModal({ shareURL: @state.get('shareURL'), @eventProperties })
      @openModalView(modal)
      modal.once 'replay', @onClickPlayButton, @

  destroy: ->
    @levelLoader?.destroy()
    @surface?.destroy()
    @god?.destroy()
    @goalManager?.destroy()
    @scriptManager?.destroy()
    delete window.world # not sure where this is set, but this is one way to clean it up
    super()