//Augment Module
var DSP = (function(dsp){
  "use strict";
  //Aliases
  var scene, protot, _this;
  dsp.scene = dsp.scene || Object.create(null);
  scene = dsp.scene;

  //CONST
  //DIR ANGLES we, nw, ne, ea, se, sw
  var DIR_ANGLES = [0,30,150,180,220,320];
  var EN_PATH = {
      we: [{x:0, y:342}, {x:100, y:342}, {x:250, y:342}, {x:385, y:342}],
      nw: [{x:0, y:150}, {x:120, y:220}, {x:260, y:275}, {x:400, y:295}],
      ne: [{x:1020, y:150}, {x:900, y:220}, {x:750, y:255}, {x:620, y:295}],
      ea: [{x:1020, y:342}, {x:930, y:342}, {x:790, y:342}, {x:660,y:342}],
      se: [{x:1020, y:550}, {x:885, y:485}, {x:745, y:415}, {x:620,y:370}],
      sw: [{x:0, y:550}, {x:135, y:485}, {x:280, y:415}, {x:400, y:370}]
  };
  var TILE_DIST = 100;
  var MAX_EN = 5;
  var MAX_SHEEP = 2;
  var INITIAL_POS = null;

  dsp.displays.David.setTileDist(TILE_DIST);
  dsp.displays.David.setDirArray(DIR_ANGLES);
  dsp.displays.Enemy.setPath(EN_PATH);
  dsp.displays.Enemy.setDirArray(DIR_ANGLES);

  //privates
  var _playLayer, _enLayer, _hudLayer;
  var _ac,_sprBG, _sprDavid, _sprSheep, _sprEnemies, _enMoving, _bearKill, _lionKill, _currentEn,
      _currentTarget, _numScore, _btnPause, _disableInteractive, _isGameOver, _isPlayerReturn;

  var _scoreContainer;

  scene.GameScene = function(){
    this.super.call(this);
    _this = this;

      //frame by frame loop
      var loop = function(dt){
        dt = dt * .001;
        _ac += dt;
        while (_ac >= (1/60)) {
            fixLoop(dt);
            _ac -= (1/60);
        }
      };

      //fixed timestep loop
      var fixLoop = function(dt){
        // toggleGlow();
        if(_disableInteractive) return;
        if(_sprDavid.revCheck()){
          moveEnemies();
          if(_sprEnemies.length < 2) {
            generateEnemy();
          }
        }
      }

      var toggleGlow = function(){
        for(var i = 0, len = _sprEnemies.length; i < len; i++){
          if(_sprEnemies[i].currentAngle === _sprDavid.currentAngle){
            _sprEnemies[i].enableGlow = true;
          }else{
            _sprEnemies[i].enableGlow = false;
          }
        }
      }

      var gameOverCheck = function(){
        if(_isGameOver) return;
        var abDist, tDist;
        for(var i = 0, len = _sprEnemies.length; i < len; i++){
          if(_sprEnemies[i].currentDistance >= 4){
            _isGameOver = true;
            break;
          }
        }
        if(_isGameOver){
          _sprSheep.playVO();
          _sprDavid.stop();
          _playLayer.interactive = false;
          /*var gOverPopup = new EHDI.popup.PostGamePopUp(getStars(), _scoreContainer.getScore());
          gOverPopup.x = dsp.SceneMgr.getStageWidth() * 0.5;
          gOverPopup.y = dsp.SceneMgr.getStageHeight() * 0.5;
          setTimeout(function(){
            dsp.SceneMgr.pushPopUp(gOverPopup, {alpha : new EHDI.scene.TransitionParameter(0, 1), duration : 0.5} );
            _btnPause.endGame();
          }, 500)*/
            setTimeout(function(){
                if( _scoreContainer.getScore() > EHDI.GAME.saveData.highScore) {
                    EHDI.GAME.saveData.highScore =  _scoreContainer.getScore();
                    EHDI.sbGame.saveGameData(EHDI.GAME.saveData, "DEFAULT", function(){
                        console.log("data saved.");
                    });
                }
              EHDI.sbGame.end(_scoreContainer.getScore());
              _btnPause.endGame();
            }, 500)
        }
      }

    var getStars = function(){
      var star = 0;
      if(_scoreContainer.getScore() >= 250) star++;
      if(_scoreContainer.getScore() >= 500) star++;
      if(_scoreContainer.getScore() >= 1000) star++;

      return star;
    }

    var getEnemyForInteraction = function(){
      var ens = [];
      for(var i = 0, len = _sprEnemies.length; i < len; i++){
        if(_sprDavid.currentAngle === _sprEnemies[i].currentAngle) ens.push(_sprEnemies[i]);
      }

      if(ens.length > 1){
        //sort
        for(var i = 1; i < ens.length; ++i) {
          var temp = ens[i];
          var j = i - 1;
          for(;j >= 0 && ens[j].currentDistance < temp.currentDistance; --j) {
            ens[j+1] = ens[j];
          }
          ens[j+1] = temp;
        }
      }
      if(ens.length > 0) return ens[0]
      return null;
    }

    var generateEnemy = function(){
      // if(_sprEnemies.length === MAX_EN) return;
      if(_sprEnemies.length === _currentEn) return;
      var randomAngle = getRandomAngle();
      var en;
      if(_bearKill < 6){
        en = new DSP.displays.Enemy("bear");
      }else if (_bearKill > 30 && Math.random() < 0.8){
        en = new DSP.displays.Enemy("lion");
      }else en = new DSP.displays.Enemy();
      en.initPath(randomAngle)
      _sprEnemies.push(en);
      en.playVO();
      // _enLayer.addChild(en);
      if(randomAngle === DIR_ANGLES[1] || randomAngle === DIR_ANGLES[2]){
        _enLayer.addChildAt(en, 0);
      }else _enLayer.addChild(en);
    }

    var getRandomAngle = function(){
      var dir_angles = DIR_ANGLES.slice();
      var index = dir_angles.indexOf(_sprDavid.currentAngle);
      if(index > -1) dir_angles.splice(index, 1);

      for(var i = 0; i < _sprEnemies.length; i++){
        index = dir_angles.indexOf(_sprEnemies[i].currentAngle);
        if(index > -1) dir_angles.splice(index, 1);
      }

      return dir_angles[Math.floor(Math.random()*dir_angles.length)];
    }

    var moveEnemies = function(except){
      for(var i = 0, len = _sprEnemies.length; i < len; i++){
        if(_sprEnemies[i] === except) continue;
        if(_sprEnemies[i].type === "bear" && _sprEnemies[i].momentum > 0){
          _sprEnemies[i].move();
          _sprEnemies[i].momentum = 0;
        }else if(_sprEnemies[i].type === "lion"){
          _sprEnemies[i].move();
          _sprEnemies[i].momentum = 0;
        }else{
          if(_bearKill > 24 && _sprEnemies[i].currentDistance === 0){
            _sprEnemies[i].move();
            _sprEnemies[i].momentum = 0;
          }else _sprEnemies[i].momentum++;
        }
      }
      gameOverCheck();
    }

    var destroyEnemy = function(){
      if(!(_currentTarget instanceof DSP.displays.Enemy)) return;
      //throw new Error("not an instance of enemy");
      var index = _sprEnemies.indexOf(_currentTarget);
      if(index > -1){
        var en = _sprEnemies.splice(index, 1)[0];
      }
      _this.removeChild(en);
      _currentTarget.destroy({children: true});
      _currentTarget = null;
    }

    var destroyAllEnemies = function(){
      var en;
      while(_sprEnemies.length > 0){
        en = _sprEnemies.pop();
        en.destroy({children: true});
      }
    }

    var engageEnemy = function(){
      if(!(_currentTarget instanceof DSP.displays.Enemy) || _isGameOver) return;// throw new Error("not an instance of enemy");

      if(_currentTarget.type === "bear"){
        _bearKill++;
      }else _lionKill++;

      if((_bearKill + _lionKill) >= 8 && _currentEn <= 2) _currentEn++;
      if((_bearKill + _lionKill) >= 12 && _currentEn <= 3 && (Math.random() < 0.4)) _currentEn++;
      if((_bearKill + _lionKill) >= 32 && _currentEn != MAX_EN && (Math.random() < 0.8))  _currentEn++;

      var points = (_currentTarget.type === "bear") ? 1 : 1.5;
      var pmultiplier = 30 - (10 * (_currentTarget.currentDistance));
      pmultiplier = (pmultiplier <= 0) ? 5 : pmultiplier;
      points *= pmultiplier;
      _scoreContainer.addScore(Math.ceil(points));
      //shake
      TweenMax.to(_playLayer, 0.025, {x: "+=2", yoyo:true, repeat:5});
      TweenMax.to(_playLayer, 0.025, {x: "-=2", yoyo:true, repeat:5});

      _currentTarget.animateHit();
      _sprDavid.attack(killTarget);
    }

    var killTarget = function(){
      _sprDavid.resetPos(true);
      _isPlayerReturn = true;
      if(_currentTarget instanceof DSP.displays.Enemy) _currentTarget.animateDeath(nextWave);
      // _sprDavid.resetPos();
    }

    var nextWave = function(){
      if(Math.random() < 0.5 && _numScore > 500 && _sprEnemies.length > 2){
        generateEnemy();
      }else generateEnemy();
      destroyEnemy();
      if(!_isPlayerReturn){
        _sprDavid.resetPos(true, function(){_disableInteractive = false;});
      }else{
        _disableInteractive = false;
      }
      _isPlayerReturn = false;
    }

    var mouseDown_Handler = function(){
      // _sprDavid.start();
    }

    var mouseUp_Handler = function(){
      // _sprDavid.stop();
    }

    var mouseClick_Handler = function(){
      if(_disableInteractive) return;

      _disableInteractive = true;
      _currentTarget = getEnemyForInteraction();
      moveEnemies(_currentTarget);
      if(_currentTarget instanceof dsp.displays.Enemy){
        var path = getHitPath();
        _sprDavid.move({path: path, spd: path.spd, callback: engageEnemy, height: path.height});
      }else{
        _sprDavid.move({spd: 0.5, callback: nextWave, miss: true});
      }
      //generate enemy
      if(_sprEnemies.length < 2){
        generateEnemy();
      }else if(Math.random() < 0.3) generateEnemy();
    }

    var getHitPath = function(){
      var path = {
          x: _currentTarget.x,
          y: _currentTarget.y,
          spd: 0.3
      }

      if((_currentTarget.currentDistance === 0 ||
         _currentTarget.currentDistance === 1) &&
         (_currentTarget.currentAngle === DIR_ANGLES[1] ||
          _currentTarget.currentAngle === DIR_ANGLES[2])){
            path.height = 250;
          }

      if((_currentTarget.currentDistance === 0) && (_currentTarget.currentAngle === DIR_ANGLES[4] ||
          _currentTarget.currentAngle === DIR_ANGLES[5])){
            path.height = 50;
          }

      switch(_currentTarget.currentDistance){
        case 2:
        case 3:
          path.spd = 0.2;
          break;
        default:
          path.spd = 0.3;
          break;
      }

      if(_currentTarget.type === "bear"){
        path.x += ((_currentTarget.scale.x === -1) ? 130 : -120)
      }else{
        path.x += ((_currentTarget.scale.x === -1) ? 110 : -100)
      }
      return path;
    }

    var setInteractive = function(){
      _playLayer.interactive = true;
      _playLayer.touchstart = _playLayer.mousedown = mouseDown_Handler;
      _playLayer.touchend = _playLayer.mouseup = _playLayer.touchendoutside = _playLayer.mouseupoutside = mouseUp_Handler;
      _playLayer.tap = _playLayer.click = mouseClick_Handler;
    }

    this.screenWillAppear = function(){
      if(!INITIAL_POS) INITIAL_POS = {x: 512, y: 342}/*{x: dsp.SceneMgr.getStageWidth() * 0.5,
                                      y: dsp.SceneMgr.getStageHeight() * 0.57};*/
      _ac = 0;
      _numScore = 0;
      _bearKill = 0;
      _lionKill = 0;
      _isGameOver = false;
      _isPlayerReturn = false;
      _currentTarget = null;
      _currentEn = 2;
      _disableInteractive = false;
      _playLayer = new EHDI.aka.Container();
      _enLayer = new EHDI.aka.Container();
      _hudLayer = new EHDI.aka.Container();
      _this.addChild(_playLayer);
      _this.addChild(_hudLayer);

      _sprEnemies = [];

      _sprBG = new EHDI.aka.Sprite(EHDI.Assets.images["bg_game"]);
      _sprBG.scale.x = 1.01;

      _sprDavid = new DSP.displays.David();
      _sprDavid.setInitialPos(INITIAL_POS.x, INITIAL_POS.y);
      _sprDavid.moveUpdateCallback = toggleGlow;

      _sprSheep = new dsp.displays.Sheep();
      _sprSheep.position.set(dsp.SceneMgr.getStageWidth() * 0.5, dsp.SceneMgr.getStageHeight() * 0.56);

      //_btnPause = new EHDI.displays.Button(EHDI.Assets.images["pause-button"], EHDI.Assets.images["pause-button-hit"]);
      _btnPause = new EHDI.components.pauseButton();
      _btnPause.position.set(dsp.SceneMgr.getStageWidth() - (_btnPause.width * 0.55), (_btnPause.height * 0.5) + 5);

      _playLayer.addChild(_sprBG);
    }


    this.startGame = function(){
      dsp.UpdateMgr.addFrameListener(loop);

      setInteractive();
      _sprDavid.start();
      generateEnemy();
    }

    this.screenDidAppear = function(){

      _playLayer.addChild(_sprSheep);
      _playLayer.addChild(_enLayer);
      _playLayer.addChild(_sprDavid);
      _hudLayer.addChild(_btnPause);

      _scoreContainer = EHDI.components.ScoreManager(this);
      _scoreContainer.setXY(20,15);
      // _scoreContainer.toggleEffects(true);
      // _scoreContainer.toggleFlash(true);
      if(EHDI.GAME.saveData.isFirstTimePlay){
        var htp = new EHDI.popup.HTPPopUp(this.startGame.bind(this));
        htp.position.set(EHDI.GAME.sceneManager.getStageWidth() * 0.5,
        EHDI.GAME.sceneManager.getStageHeight() * 0.5);
        EHDI.GAME.sceneManager.pushPopUp(htp,
        {alpha : new EHDI.scene.TransitionParameter(0, 1), duration : 0.1});
      }else{
        this.startGame();
      }
    }

    this.screenDidDisappear = function(){
      _sprDavid.destroy({children: true});
      dsp.UpdateMgr.removeFrameListener(loop);
      dsp.SoundMgr.stopBGM();
      _btnPause.endGame();
      _btnPause.dispose();
      _scoreContainer.dispose();
      TweenMax.killAll();
      destroyAllEnemies();
      this.destroy({children: true});
    }

    this.popUpDidAppear = function(){
      DSP.DBoneFactory.enableClock = false;
      _sprDavid.pause();
      if(!_isGameOver){
        TweenMax.pauseAll();
      }else _btnPause.endGame();
    }

    this.popUpDidDisappear = function(){
      if(!_isGameOver){
        DSP.DBoneFactory.enableClock = true;
        _sprDavid.resume();
        TweenMax.resumeAll();
      }
    }
  }

  protot = scene.GameScene.prototype = Object.create(EHDI.aka.Container.prototype)

  protot.constructor = scene.GameScene;

  protot.super = EHDI.aka.Container;

  return dsp;
}(DSP || Object.create(null)));