//
//  GameScene.cpp
//  RedCore2
//
//  Created by Gabriel Capella on 31/05/17.
//
//

#include "GameScene.h"
#include "SimpleAudioEngine.h"
#include "BlocksLayer.h"
#include "Ball.h"
#include "params.h"

USING_NS_CC;

Scene* GameScene::createScene() {
    auto scene = Scene::createWithPhysics();
    Size visibleSize = Director::getInstance()->getVisibleSize();
    
    //choose whitch part need to draw, Joint, Shape, Contact, None or All
    //scene->getPhysicsWorld()->setDebugDrawMask(PhysicsWorld::DEBUGDRAW_ALL);
    
    auto layer = GameScene::create();
    scene->addChild(layer);
    
    auto material = PHYSICSBODY_MATERIAL_DEFAULT;
    material.density = 1.0f;
    material.restitution = 1.0f;
    material.friction = 0.0f;
    
    // the edge of the screen
    visibleSize.height += BALL_SIZE;
    auto body = PhysicsBody::createEdgeBox(visibleSize, material);
    auto edgeNode = Node::create();
    edgeNode->setPosition(Point(visibleSize.width/2,visibleSize.height/2-BALL_SIZE));
    body->setDynamic(false);
    edgeNode->setPhysicsBody(body);
    scene->addChild(edgeNode);
    
    return scene;
}

// on "init" you need to initialize your instance
bool GameScene::init() {
    //////////////////////////////
    // 1. super init first
    if ( !Layer::init() ) {
        return false;
    }
    
    auto visibleSize = Director::getInstance()->getVisibleSize();
    Vec2 origin = Director::getInstance()->getVisibleOrigin();
    
    // Adiona o fundo
    auto bg = LayerColor::create(COLOR_back);
    this->addChild(bg);
    
    
    auto ball = Ball::create();
    ball->setPosition(visibleSize.width / 2, BALL_SIZE*2);
    ball->throwBall();
    this->addChild(ball, 21);
    
    auto blocks = BlocksLayer::create();
    blocks->setPosition(visibleSize.width/2, visibleSize.height);
    this->addChild(blocks, 20);
    
    raquete = DrawNode::create();
    float py = RAQUETE_HEIGHT/2.0;
    float pxl = - RAQUETE_WIDTH/2;
    float pxr =  RAQUETE_WIDTH/2;
    raquete->drawSegment(Vec2(pxl, py), Vec2(pxr, py), py, Color4F(COLOR_grey));
    raquete->setPositionX(visibleSize.width/2);
    
    auto bsize = Size(RAQUETE_WIDTH+RAQUETE_HEIGHT, RAQUETE_HEIGHT);
    auto physicsBody = PhysicsBody::createBox(bsize, PhysicsMaterial(0.1f, 1.0f, 0.0f));
    physicsBody->setPositionOffset(Vec2(0, RAQUETE_HEIGHT/2));
    physicsBody->setGravityEnable(false);
    physicsBody->setDynamic(false);
    physicsBody->setContactTestBitmask(0xFFFFFFFF);
    raquete->addComponent(physicsBody);
    
    this->addChild(raquete);
    
    auto listener1 = EventListenerTouchOneByOne::create();
    
    // trigger when you push down
    listener1->onTouchBegan = [=](Touch* touch, Event* event){
        raquete->setPositionX(touch->getLocation().x);
        float px = touch->getLocation().x;
        if (px >= RAQUETE_WIDTH/2 && px < visibleSize.width - RAQUETE_WIDTH/2)
            raquete->setPositionX(touch->getLocation().x);
        return true; // if you are consuming it
    };
    
    // trigger when moving touch
    listener1->onTouchMoved = [=](Touch* touch, Event* event){
        float px = touch->getLocation().x;
        if (px >= RAQUETE_WIDTH/2 && px <= visibleSize.width - RAQUETE_WIDTH/2)
            raquete->setPositionX(touch->getLocation().x);
    };
    

    // Add listener
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, this);

    // the edge of bottom
    auto body = PhysicsBody::createEdgeBox(Size(visibleSize.width, 0));
    auto edgeNode = Node::create();
    edgeNode->setPosition(Point(visibleSize.width/2, -BALL_SIZE));
    body->setDynamic(false);
    edgeNode->setTag(BOTTOM_TAG);
    body->setContactTestBitmask(0xFFFFFFFF);
    edgeNode->setPhysicsBody(body);
    this->addChild(edgeNode);
    
    // Evento no contato das bolas
    auto contactListener = EventListenerPhysicsContact::create();
    contactListener->onContactBegin = CC_CALLBACK_1(GameScene::onContactBegin, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(contactListener, this);
    
    return true;
}

bool GameScene::onContactBegin(PhysicsContact& contact) {
    auto nodeA = contact.getShapeA()->getBody()->getNode();
    auto nodeB = contact.getShapeB()->getBody()->getNode();
    
    if (nodeA && nodeB && nodeA->getTag() != nodeB->getTag()) {
        CCLOG("%d %d", nodeB->getTag(), nodeA->getTag());
        
        if (nodeA->getTag() == BLOCK_TAG && nodeB->getTag() != INDESTRUCTIBLE_BLOCK_TAG) {
            nodeA->removeFromParentAndCleanup(true);
        } else if (nodeB->getTag() == BLOCK_TAG && nodeA->getTag() != INDESTRUCTIBLE_BLOCK_TAG) {
            nodeB->removeFromParentAndCleanup(true);
        } else if (nodeA->getTag() == BOTTOM_TAG && nodeB->getTag() == BALL_TAG) {
            ParticleSun* m_emitter = ParticleSun::create();
            m_emitter->setPosition(nodeB->getPosition());
            m_emitter->setDuration(1);
            this->getScene()->addChild(m_emitter);
            nodeB->removeFromParentAndCleanup(true);
        } else if (nodeB->getTag() == BOTTOM_TAG && nodeA->getTag() == BALL_TAG) {
            ParticleSun* m_emitter = ParticleSun::create();
            m_emitter->setPosition(nodeA->getPosition());
            m_emitter->setDuration(1);
            this->getScene()->addChild(m_emitter);
            nodeA->removeFromParentAndCleanup(true);
        }
    }
    
    //bodies can collide
    return true;
}
