#include "play.h"
#include <QDebug>


play::play(QWidget *parent) :
    QWidget(parent)
{
    // Set the background (track) variables and coords.
    x1=0;
    x2=600;
    setTrack(play::DAY);
    repaint();

    // set player score to 0
    score=0;

    // Set the obstacles to cones
    for(int i = 0; i < 3; i++){
        obs[i].setObs("cone") ;
    }

    // Set Car to red car by default.
    car.setCar("red");

    // Set level to EASY
    level = EASY;

    // Obstacles that will be displayed if level is changed.
    obs[MEDIUM].setYObstacle(145);
    obs[HARD].setYObstacle(100);

    playing = false;

    // Set timer event to move the background
    myTimer= new QTimer(this);
}

play::~play(){
    delete myTimer;
}

void play::setCar(string arg){
    car.setCar(arg);
}

play::Track play::getTrack(){
    return tt;
}

void play::paintEvent(QPaintEvent *){
    QPainter p(this);
    QString scar = QString::fromStdString(car.getCar());
    QString check = QString::fromStdString(flag.name);
    QString road = QString::fromStdString(track);
    QString cone = QString::fromStdString(obs[0].getObs());

    // Check if there is a collision every time the car is moved
    collision();

    // Check if there is a collision with the flag
    flagCollision(flag, car);

    // Draws the track
    p.drawPixmap(x1,0,600,400,QPixmap(road));
    p.drawPixmap(x2,0,610,400,QPixmap(road));

    // Draws the obstacles.
    for(int i = 0; i <= level; i++){
        p.drawPixmap(obs[i].getXObstacle(),obs[i].getYObstacle() + i,35,35,QPixmap(cone));
    }

    //Draws the flag
    p.drawPixmap(flag.getXFlag(),flag.getYFlag(),50,50,QPixmap(check));
    // Draws the Car
    p.drawPixmap(10,car.getYCar(),80,50,QPixmap(scar));

    //Updates the obstacles always that there is a new scene
        if (x1 < -600){
            updateObs();
            x1 = 599;
        }
    // Same as above but with new background.
        if(x2 < -600){
            updateObs();
            x2 = 599;
        }

    // increase player score.
    setScore();
}

int play::randInt(int min, int max){
    return qrand() % ((max +1 )- min) +  min ;
}

// Whenever there is collision with an obstacle the game
// is stoped.
void play::stopGame(){
    myTimer->stop();
}

// Function to increase the player score.
void play::setScore(int n){
    score += n ;
}

// Returns the score.
int play::getScore(){
    return score;
}


// Function called everytime a timer event ocurrs.
// It repaints the graphics of the game.
void play::mySlot(){

    //moves road, obstacles, flags
    x1 = x1-STEPS;
    x2 = x2-STEPS;

    for(int i = 0; i <= level; i++){
        obs[i].setXObstacle(obs[i].getXObstacle() - STEPS);
    }
    flag.setXFlag(flag.getXFlag()-STEPS);

    repaint();
}

// Restart the timer
void play::run(){
    playing = true;
    connect(myTimer, SIGNAL(timeout()), this, SLOT(mySlot()));
    myTimer->start(16);
}

// Resets the game to its initial state if the game is reset.
void play::newGame(){
    x1 = 0;
    x2 = 600;
    score=0;
    myTimer = new QTimer(this);
    setTrack(getTrack());

    //moves road, obstacles, flags
    x1 = x1-STEPS;
    x2 = x2-STEPS;

    for(int i = 0; i <= level; i++){
        obs[i].setXObstacle(obs[i].getXObstacle() - STEPS);
    }
    flag.setXFlag(flag.getXFlag()-STEPS);

    repaint();
    run();
}

// Sets the images of the obstacles.
void play::setObstaclesPixmap(string pixmap){

    for (int i = 0; i < 3; i++){
        obs[i].setObs(pixmap) ;
    }
}

// Event for the controls of the car.
void play::keyPressEvent(QKeyEvent *event){

    if((event->key() == Qt::Key_Up) && car.getYCar() > 80){
        car.setYCar(car.getYCar()-30);
    }

    if((event->key() == Qt::Key_Down) && car.getYCar() < 280){
        car.setYCar(car.getYCar()+30);
    }

}


// Updates the obstacles position. Called from the Paint function when
// the trac is finished.
void play::updateObs(){

int obstacles[4] ;
int shuffle_start ;
int xflag = x1 ;
int xobs = x1;

    updateObstacleYCoordinate(obstacles[0], obstacles[1], obstacles[2], obstacles[3]);

    if (x1 < 600){
        xflag = 600;
        xobs = 550;
    }

    if( x1 < 600 || x2 < 600){
        shuffle_start = randInt(0,3) ;
        flag.setYFlag(obstacles[shuffle_start]);
        flag.setXFlag(xflag);
        for(int i = 0; i < 3; i++){
            obs[i].setYObstacle(obstacles[(shuffle_start + i + 1) % 4]);
            obs[i].setXObstacle(xobs);
        }
    }

}


// Function to detect collisions with the obstacles.
void play::collision(){
    // There will be at least obstacle no matter the
    // game level, check collision with first obstacle
    if(obstacleCollision(obs[0], car)){
        //qDebug() << "Collision!!" ;
        stopGame();
        playing = false ;
    }
    // If there is no collision with first obstacle, but
    // there is a second obstacle, check collision
    else if(level > EASY && obstacleCollision(obs[1], car)){
          //qDebug() << "Collision!!" ;
          stopGame();
          playing = false ;
    }
    //If there is no collision with the previous 2 obstacles,
    //but there is a third obstacle, check collision
    else if(level == HARD && obstacleCollision(obs[2], car)){
          //qDebug() << "Collision!!" ;
          stopGame();
          playing = false ;
    }

}


void play::updateObstacleYCoordinate(int &obj1, int &obj2, int &obj3, int &obj4){
    // The game presents 3 bad obstacle and one safe obstacle every x distance.
    // In this function you will compute the Y coordinate of such obstacles.
    // You need make sure that no two obstacle overlap each other.
    // Each obstacle is 40px of height, the top coordinate of the racetrack is
    // 80px and the bottom coordinate of the racetrack is 280.
    // Hint randInt(min, max)

    obj1 = randInt(80, 245 - 40*4) ;

    obj2 = randInt(obj1 + 40, 245 - 40 * 3) ;

    obj3 = randInt(obj2 + 40, 245 - 40 * 2) ;

    obj4 =  randInt(obj3 + 40, 245) ;

    //qDebug() << obj1 << obj2 << obj3 << obj4 ;

}

void play::setTrackPixmap(Track track_type){

    tt  = track_type ;

    switch(track_type){
        case play::DAY:
            //All background picture follow the same path but with different names e.g. ":/resources/blahblah.png"
            track = ":/resources/coolroad.png" ;
        break ;
        case play::NIGHT:
            track = ":/resources/roadnight.png";
        break ;
        case play::BEACH:
            track = ":/resources/roadsand.png";
        break ;
        case play::CANDYLAND:
            track = ":/resources/candyroad.png";
        break ;
    } ;

}

string play::getTrackPixmap(){

    return track ;
}
