/*****************
* Scene.cpp code *
*****************/

//Update the cooldown on each powerup, and check if any power up is in the immediate vicinity of a kart
void Scene::checkPowerups(float deltaT) {
   int xLoc;
   int zLoc;

   if (boostCam) {
      camVal -= deltaT;
   }

   if (camVal <= 0) {
      applyBoost(false);
   }

   //New powerup data structure traversal to update cooldowns
   for (int i = 0; i < cooldownList.size(); i++) {
      xLoc = (cooldownList[i].mapLocation.x + 650) / 50;
      zLoc = (cooldownList[i].mapLocation.z + 300) / 50;

      if (cooldownList[i].cdTimer > 0) {
         cooldownList[i].cdTimer -= deltaT;
         
            if (powerupUSS[xLoc][zLoc].model != NULL) {
                glm::vec3 pos = powerupUSS[xLoc][zLoc].model->getTranslation();
                pos.y = cooldownList[i].mapLocation.y - cooldownList[i].cdTimer * 3;
                powerupUSS[xLoc][zLoc].model->setTranslation(pos);
            }
      }

      if (cooldownList[i].cdTimer <= 0) {
         cooldownList.erase(cooldownList.begin() + i);
         powerupUSS[xLoc][zLoc].cdTimer = 0;
      }

   }

   std::vector<std::shared_ptr<KartControl> >::iterator controlKart = controlKarts.begin();
   int count = 0;
   //check the immediate vicinity, as well as all 8 nearby areas for powerups
   for (; controlKart != controlKarts.end(); controlKart++) {
      glm::vec3 kartPos = (*controlKart)->getPosition();
      xLoc = (kartPos.x + 650) / 50;
      zLoc = (kartPos.z + 300) / 50;
      
      for (int i = -1; i < 2; i++) {
         for (int j = -1; j < 2; j++) {
            if (xLoc+i < 0 || zLoc+j < 0) continue;
            
            if (powerupUSS[xLoc + i][zLoc + j].cdTimer <= 0 && glm::length(powerupUSS[xLoc + i][zLoc + j].mapLocation - kartPos) < 7) {
               //you are currently on a powerup!
               powerupUSS[xLoc + i][zLoc + j].cdTimer = 2;
               cooldownList.push_back(powerupUSS[xLoc + i][zLoc + j]);
               assignPowerup(count, powerupUSS[xLoc + i][zLoc + j]);
                    particles.createExplosion(kartPos);
               (*controlKart)->gotItem = true;
               break;
            }
         }
      }
      count++;
   }
}


/*********************
* GameLogic.cpp code *
*********************/

//Check if any kart is off course. If so, place it at its prevPoint
void GameLogic::checkKarts() {
   for (int i = 0; i < kartList.size(); i++) {
        //If we have fallen, set us back on the track!
      if (fabs(spline[kartList[i].prevPoint].y) - fabs(kartList[i].kart->getPosition().y) < -20 &&
         spline[kartList[i].prevPoint].y > kartList[i].kart->getPosition().y) {
         kartList[i].kart->reset = true;       
      }
        //If reset is set to true, reset that kart (Done with Robert Burton)
        if (kartList[i].kart->reset == true) {
            
            kartList[i].kart->reset = false;
            kartList[i].kart->setPosition(spline[kartList[i].prevPoint]+glm::vec3(0,1,0));
         kartList[i].kart->setAccelerating(false, true);
            
            glm::vec3 direction = glm::normalize(spline[kartList[i].nextPoint] - spline[kartList[i].prevPoint]);

            float rad = acos(glm::dot(glm::vec3(0.0,0.0,1.0), direction));
            
            glm::vec3 axis = glm::cross(glm::vec3(0.0,0.0,1.0), direction);
            
            glm::vec3 ax = glm::normalize(axis);
            ax *= sinf(rad / 2.0f);
            float scalar = cosf(rad / 2.0f);
            glm::quat offset(scalar, ax.x, ax.y, ax.z);
            kartList[i].kart->setRotation(offset);
            
            kartList[i].kart->setDrop(true);
        }
   }
}

//Check if a kart has chosen to use a power up. If so, use it!
void GameLogic::checkTriggeredPowerups() {
   for (int i = 0; i < kartList.size(); i++) {
      if (kartList[i].kart->powerup) {
         //B-B-B-BOOSTER!
         if(scene->getKartPowerup(i) == PowerupType::Boost) {
            if (i == 0) {
               scene->applyBoost(true);
               scene->camVal = .75;
            }
            kartList[i].kart->setPowerUpBoost(true);
            kartList[i].kart->boostUsed = true;
            scene->setKartPowerup(i, PowerupType::None);
         }
         //FIYAH ZE MISSILES!
         if(scene->getKartPowerup(i) == PowerupType::Missile) {
            if(getKartPlaceInt(i) != 1) {
               kartList[i].kart->missileFired = true;
                    glm::vec3 dir = glm::vec3(0,0,1)*scene->getMainPlayer()->getRotation();
                    scene->rockets.addRocket(kartList[i].kart->getPosition(), dir, 4.0, getKartAtPlace(getKartPlaceInt(i)-1).kart);
               scene->setKartPowerup(i, PowerupType::None);
                }
         }
      }
      kartList[i].kart->enablePowerup(false);
   }
}

//update prevPoint, nextPoint, and lap according to kart's distance to spline points
void GameLogic::updatePoints() {
    for (int i = 0; i < kartList.size(); i++) {
        float nextDist = glm::length(spline[kartList[i].nextPoint] - kartList[i].kart->getPosition());
        float prevDist = glm::length(spline[kartList[i].prevPoint] - kartList[i].kart->getPosition());
        
        if (nextDist < prevDist) {
            if(i == 0) {
                goingBackwards = 0;
            }
            kartList[i].nextPoint++;
            kartList[i].prevPoint++;
            kartList[i].pointsCrossed++;
        }
        if (kartList[i].pointsCrossed >= static_cast<int>(spline.size())) {
            kartList[i].pointsCrossed = 0;
            kartList[i].lap++;
        }
        if (kartList[i].nextPoint >= spline.size()) {
            kartList[i].nextPoint = 0;
        }
        if (kartList[i].prevPoint >= spline.size()) {
            kartList[i].prevPoint = 0;
        }
        
        //Going backwards (In case of players going all the way around the map backwards, they have to make up that lap)
        if(kartList[i].prevPoint-1 >= 0) {
            float prevPrevDist = glm::length(spline[kartList[i].prevPoint-1] - kartList[i].kart->getPosition());
            if(prevPrevDist < prevDist) {
                if(i == 0) {
                    goingBackwards++;
                }
                kartList[i].prevPoint--;
                kartList[i].nextPoint--;
                kartList[i].pointsCrossed--;
            }
            if(kartList[i].nextPoint < 0) {
                kartList[i].nextPoint = static_cast<int>(spline.size())-1;
            }
        }
        else if(kartList[i].prevPoint-1 < 0) {
            float prevPrevDist = glm::length(spline[spline.size()-1] - kartList[i].kart->getPosition());
            if(prevPrevDist < prevDist) {
                kartList[i].prevPoint = static_cast<int>(spline.size())-1;
                kartList[i].nextPoint--;
                kartList[i].pointsCrossed--;
            }
        }
    }
}