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


Scene::Scene(QObject *parent) : QGraphicsScene(parent)
{
    leftPressed = false;
    leftPressed = false;
    bulletAmount = 0;
    level = -1;
    puntosJugador = 0;
    puntos = new QGraphicsTextItem("0");
    puntos->setDefaultTextColor(QColor::fromRgb(0,0,0));
    puntos->setFont(QFont("Times", 12, QFont::Bold));
    gameOverTimer = new QTimer(this);
    connect(gameOverTimer,&QTimer::timeout,this,[=](){
        gameOverTimer->stop();
        puntosJugador = jugador->getPoints()->getPoints();
        jugador->getPoints()->changeAmountPoints(-puntosJugador);
        puntosJugador = 0;
        cleanScene();
        setStartScreen();
    });
    jugador = nullptr;
}

Scene::~Scene()
{
    cleanScene();
    delete botHB;
    delete topHB;
    delete westHB;
    delete eastHB;
    delete gameOverTimer;
    delete jugador;
    delete fondo;
    delete puntos;
}

void Scene::addPlayer(int x, int y)
{
    jugador = new donFedeJugador(QPixmap(":/ImagenesDeProyecto/DonFede8bit.png"));
    jugador->setLevel(level);
    addItem(jugador);
    connectPlayerHB();
    jugador->setX(x);
    jugador->setY(y);
    jugador->fallingPlayer();
}

void Scene::addBottomHB()
{
    botHB = new bottomHitbox(QPixmap(":/ImagenesDeProyecto/horizontalHitbox.png"));
    addItem(botHB);
    botHB->setPos(QPointF(0,0));
}

void Scene::addTopHB()
{
    topHB = new topHitbox(QPixmap(":/ImagenesDeProyecto/horizontalHitbox.png"));
    addItem(topHB);
    topHB->setPos(QPointF(0,0));
}

void Scene::addWestHB()
{
    westHB = new westHitbox(QPixmap(":/ImagenesDeProyecto/verticalHitbox.png"));
    addItem(westHB);
    westHB->setPos(QPointF(0,0));
}

void Scene::addEastHB()
{
    eastHB = new eastHitbox(QPixmap(":/ImagenesDeProyecto/verticalHitbox.png"));
    addItem(eastHB);
    eastHB->setPos(QPointF(0,0));
}

void Scene::connectPlayerHB()
{
    // Conexiones Hitbox inferior
    connect(jugador,&donFedeJugador::yChanged,botHB,&bottomHitbox::newPos);
    connect(jugador,&donFedeJugador::xChanged,botHB,&bottomHitbox::newPos);
    connect(botHB,&bottomHitbox::movedHB,jugador,&donFedeJugador::collidesFloor);

    connect(jugador,&donFedeJugador::stoppedJumping,botHB,&bottomHitbox::emitFallingCheck);
    connect(botHB,&bottomHitbox::fallingCheck,jugador,&donFedeJugador::collidesFloor);

    // Conexiones Hitbox superior
    connect(jugador,&donFedeJugador::yChanged,topHB,&topHitbox::newPos);
    connect(jugador,&donFedeJugador::xChanged,topHB,&topHitbox::newPos);
    connect(topHB,&topHitbox::movedHB,jugador,&donFedeJugador::collidesRoof);

    // Conexiones Hitbox izquierdo
    connect(jugador,&donFedeJugador::yChanged,westHB,&westHitbox::newPos);
    connect(jugador,&donFedeJugador::xChanged,westHB,&westHitbox::newPos);
    connect(westHB,&westHitbox::movedHB,jugador,&donFedeJugador::collidesWallW);

    // Conexiones Hitbox derecho
    connect(jugador,&donFedeJugador::yChanged,eastHB,&eastHitbox::newPos);
    connect(jugador,&donFedeJugador::xChanged,eastHB,&eastHitbox::newPos);
    connect(eastHB,&eastHitbox::movedHB,jugador,&donFedeJugador::collidesWallE);
}

void Scene::addBackground(QPixmap pixmap)
{
    fondo = new background(pixmap);
    addItem(fondo);
    fondo->setPos(QPointF(0,0)-QPointF(fondo->boundingRect().width()/2,fondo->boundingRect().height()/2));
}

sueloSimple * Scene::addVerticalLevelBorders(int x, int y)
{
    sueloSimple * borde = new sueloSimple(QPixmap(":/ImagenesDeProyecto/BordeExterno.png"));
    addItem(borde);
    borde->setPos(QPointF(x,y));
    return borde;
}

sueloSimple * Scene::addHorizontalLevelBorders(int x, int y)
{
    sueloSimple * borde = new sueloSimple(QPixmap(":/ImagenesDeProyecto/BordeSuperior.png"));
    addItem(borde);
    borde->setPos(QPointF(x,y));
    return borde;
}

sueloSimple *Scene::addFloorXYCoor(int x, int y)
{
    sueloSimple * suelo = new sueloSimple(QPixmap(":/ImagenesDeProyecto/Suelo.png"));
    addItem(suelo);
    suelo->setPos(QPointF(x,y));
    return suelo;
}

sueloSimple * Scene::addWallXYCoor(int x, int y)
{
    sueloSimple * muralla = new sueloSimple(QPixmap(":/ImagenesDeProyecto/Muralla.png"));
    addItem(muralla);
    muralla->setPos(QPointF(x,y));
    return muralla;
}

interactable * Scene::addDoorXYCoorType(int x, int y, int type)
{
    interactable * puerta = new interactable(QPixmap(":/ImagenesDeProyecto/Puerta.png"));
    addItem(puerta);
    puerta->setPos(QPointF(x,y));
    puerta->setInteractable(type);
    return puerta;
}

interactable * Scene::addPaltaXYCoorType(int x, int y, int type)
{
    interactable * palta = new interactable(QPixmap(":/ImagenesDeProyecto/palta8bit.png"));
    palta->setPos(QPointF(x,y));
    palta->setInteractable(type);
    addItem(palta);
    return palta;
}

interactable * Scene::addCatXYCoorType(int x, int y, int type)
{
    interactable * gato = new interactable(QPixmap(":/ImagenesDeProyecto/gatito8bit.png"));
    addItem(gato);
    gato->setPos(QPointF(x,y));
    gato->setInteractable(type);
    return gato;
}

void Scene::setPlayer(int x, int y)
{
    addBottomHB();
    addTopHB();
    addWestHB();
    addEastHB();
    addPlayer(x,y);
    jugador->getPoints()->changeAmountPoints(puntosJugador);
    connect(jugador,&donFedeJugador::outOfLives,this,[=](){
        gameOverTimer->start(5000);
    });

    addItem(puntos);
    puntos->setPos(QPointF(400,-300));
    connect(jugador,&donFedeJugador::pointsChanged,this,[=](){
        puntosJugador = jugador->getPoints()->getPoints();
        puntos->setPlainText(QString::number(jugador->getPoints()->getPoints()));
    });
}

void Scene::setStartScreen()
{
    level = -1;
    addBackground(QPixmap(":/ImagenesDeProyecto/pantallaStart.png"));

    interactable * titulos = new interactable(QPixmap(":/ImagenesDeProyecto/Titulo.png"));
    addItem(titulos);
    titulos->setPos(QPointF(-titulos->boundingRect().width()/2,-titulos->boundingRect().height()/2));
    punteros.append(titulos);

    button * botonInicio = new button(QPixmap(":/ImagenesDeProyecto/Buttons/StartButton.png"),1);
    botonInicio->setPos(QPointF(-botonInicio->boundingRect().width()/2,200));
    addItem(botonInicio);
    punteros.append(botonInicio);
    connect(botonInicio,&button::buttonPressed,this,[=](){
        cleanScene();
        setTutorial();
    });
}

void Scene::setTutorial()
{
    level = 0;
    addBackground(QPixmap(":/ImagenesDeProyecto/FondoInicial.png"));
    punteros.append(addVerticalLevelBorders(-570,-360));
    punteros.append(addVerticalLevelBorders(540,-360));
    punteros.append(addHorizontalLevelBorders(-540,-390));
    punteros.append(addHorizontalLevelBorders(-540,360));

    punteros.append(addDoorXYCoorType(265,-160,1));

    punteros.append(addFloorXYCoor(-400,300));
    punteros.append(addFloorXYCoor(-280,230));
    punteros.append(addFloorXYCoor(-160,160));
    punteros.append(addFloorXYCoor(-40,90));
    punteros.append(addFloorXYCoor(80,20));
    punteros.append(addFloorXYCoor(200,-50));
    punteros.append(addFloorXYCoor(265,-107));

    punteros.append(addFloorXYCoor(200,300));
    punteros.append(addWallXYCoor(240,280));


    punteros.append(addPaltaXYCoorType(300, 300, 2));
    punteros.append(addPaltaXYCoorType(80, 80, 2));
    punteros.append(addPaltaXYCoorType(-280, 300, 2));
    punteros.append(addPaltaXYCoorType(265, -240, 2));

    setPlayer(-540,284);
    connect(jugador,&donFedeJugador::levelFinished,this,[=](){
        cleanScene();
        setLevel1();
    });

    addItem(jugador->sendLives());
    zombieSimple* zombie1 = addBaseZombie(100,288);
    zombie1->addTrajectoryPoint(QPointF(150,288));
    zombie1->addTrajectoryPoint(QPointF(230,228));
    zombie1->addTrajectoryPoint(QPointF(200,228));
    zombie1->startTrajectory();
    punteros.append(zombie1);

    background * mensajeTutorial = new background(QPixmap(":/ImagenesDeProyecto/DialogoTutorial.png"));
    mensajeTutorial->setPos(QPointF(-mensajeTutorial->boundingRect().width()/2,
                                    -mensajeTutorial->boundingRect().height()/2));
    addItem(mensajeTutorial);

    button * botonEndTutorial = new button(QPixmap(":/ImagenesDeProyecto/Buttons/EndTutorialButton.png"),1);
    botonEndTutorial->setPos(QPointF(-botonEndTutorial->boundingRect().width()/2,100));
    addItem(botonEndTutorial);
    connect(botonEndTutorial,&button::buttonPressed,this,[=](){
        removeItem(mensajeTutorial);
        delete(mensajeTutorial);
        removeItem(botonEndTutorial);
        delete(botonEndTutorial);
    });
}

void Scene::setLevel1()
{
    level = 1;
    addBackground(QPixmap(":/ImagenesDeProyecto/FondoInicial.png"));
    punteros.append(addVerticalLevelBorders(-570,-360));
    punteros.append(addVerticalLevelBorders(540,-360));
    punteros.append(addHorizontalLevelBorders(-540,-390));
    punteros.append(addHorizontalLevelBorders(-540,360));

    setPlayer(-540,284);
    punteros.append(addPaltaXYCoorType(300, 300, 2));
    gameOverTimer->start(4000);
}

zombieSimple* Scene::addBaseZombie(int x, int y)
{
    zombieSimple * zombie = new zombieSimple(QPixmap(":/ImagenesDeProyecto/Zombie1erAno.png"));
    addItem(zombie);
    connect(zombie, &zombieSimple::checkMove, jugador, &donFedeJugador::checkEnemy);
    zombie->setX(x);
    zombie->setY(y);
    zombie->addTrajectoryPoint(QPointF(x,y));
    return zombie;
}

void Scene::connectProjectileZombie(proyectil * bala)
{
    QList<QGraphicsItem*> collidingItems = fondo->collidingItems();
    foreach(QGraphicsItem *item, collidingItems){
        zombieSimple * zombie = dynamic_cast<zombieSimple*>(item);
        if(zombie){
            connect(bala,&proyectil::detectedZombieColision,
                    zombie,&zombieSimple::checkProyectil);
        }
    }
}

void Scene::cleanScene()
{
    foreach(QGraphicsPixmapItem *item, punteros){
        delete(item);
        punteros.removeFirst();
    }

    if(level>-1){
        delete(botHB);
        delete(topHB);
        delete(westHB);
        delete(eastHB);
        delete(jugador);
        jugador = nullptr;
        removeItem(puntos);
    }
    removeItem(fondo);
}

void Scene::keyPressEvent(QKeyEvent *event)
{
    if(jugador != nullptr){
        if(jugador->sendLives()->getVidas()>-1){
            switch(event->key()){
            case Qt::Key_Left:
                if(!rightPressed){
                    leftPressed = true;
                    jugador->startLateralMovingLeft();
                }
                break;
            case Qt::Key_Right:
                if(!leftPressed){
                    rightPressed = true;
                    jugador->startLateralMovingRight();
                }
                break;
            case Qt::Key_Space:
                jugador->jumpingPlayer();
                break;
            case Qt::Key_Up:
                jugador->climbPlayer();
                break;
            case Qt::Key_Z:
                jugador->checkInteract();
                break;
            case Qt::Key_X:
                if(bulletAmount<3){
                    bulletAmount++;
                    proyectil * bala =jugador->shoot();
                    connectProjectileZombie(bala);
                    connect(bala,&proyectil::xAnimationFinished,this,[=](){
                        bulletAmount--;
                        removeItem(bala);
                        delete bala;
                    });
                    connect(bala,&proyectil::detectedZombieColision,this,[=](){
                        bulletAmount--;
                        removeItem(bala);
                        delete bala;
                    });
                    addItem(bala);
                }
                break;
            }
        }
    }
}

void Scene::keyReleaseEvent(QKeyEvent *event)
{
    if(jugador != nullptr){
        if(event->key()==Qt::Key_Left){
            leftPressed = false;
            jugador->stopLateralMoving();
        }
        else if(event->key()==Qt::Key_Right){
            rightPressed = false;
            jugador->stopLateralMoving();
        }
    }
}

