#include "potator.h"
#include "scene/playercharacternode.h"
#include <btBulletCollisionCommon.h>
#include <btBulletDynamicsCommon.h>
#include "scene/scenetree.h"
#include "SparrowRenderer/parametricmesh.h"
#include "SparrowRenderer/pbrmaterial.h"
#include "scene/meshnode.h"
#include "tools/loader.h"
#include "tools/loadingthread.h"
#include "SparrowRenderer/texture.h"
#include "scene/graphicalcontainernode.h"
#include "resourcemanager.h"
#include <imgui/imgui.h>

#define PHYSICS_SHAPES_OFFSET 0.0025f

Potator::Potator(PlayerCharacterNode * player,
        int shield_action,
        int bottle_action,
        int object_action) :
    m_player(player),
    m_throwShieldAction(shield_action),
    m_throwBottleAction(bottle_action),
    m_throwObjectAction(object_action)
{
    // creating shield
    m_shieldMeshes = Loader::loadMesh("shield.obj");
    for(Mesh* m : m_shieldMeshes)
        m->initGL();

    btCompoundShape* shieldShape = new btCompoundShape();

    btTransform woodTransform = btTransform::getIdentity();
    woodTransform.setRotation(btQuaternion(0, 3.1416f, 0));
    shieldShape->addChildShape(woodTransform, new btCylinderShapeZ(btVector3(0.57f + PHYSICS_SHAPES_OFFSET, 0.57f + PHYSICS_SHAPES_OFFSET, 0.03f + PHYSICS_SHAPES_OFFSET)));
    btTransform guardTransform = btTransform::getIdentity();
    guardTransform.setOrigin(btVector3(0.f, 0.f, -0.035f));
    shieldShape->addChildShape(guardTransform, new btSphereShape(0.08 + PHYSICS_SHAPES_OFFSET));

    m_shieldShape = shieldShape;

    m_shieldMass = 0.5f;

    // creating bottle
    m_bottleMeshes = Loader::loadMesh("bottle.obj");
    for(Mesh* m : m_bottleMeshes)
        m->initGL();

    btCompoundShape* bottleShape = new btCompoundShape();
    btTransform ballTransform = btTransform::getIdentity();
    ballTransform.setOrigin(btVector3(0.f, 0.098f, 0.f));
    bottleShape->addChildShape(ballTransform, new btSphereShape(0.11 + PHYSICS_SHAPES_OFFSET));
    btTransform supportTransform = btTransform::getIdentity();
    supportTransform.setOrigin(btVector3(0.f, 0.025f, 0.f));
    bottleShape->addChildShape(supportTransform, new btCylinderShape(btVector3(0.07f + PHYSICS_SHAPES_OFFSET, 0.04f + PHYSICS_SHAPES_OFFSET, 0.07f + PHYSICS_SHAPES_OFFSET)));
    btTransform neckTransform = btTransform::getIdentity();
    neckTransform.setOrigin(btVector3(0.f, 0.26f, 0.f));
    bottleShape->addChildShape(neckTransform, new btCylinderShape(btVector3(0.03f + PHYSICS_SHAPES_OFFSET, 0.08f + PHYSICS_SHAPES_OFFSET, 0.03f + PHYSICS_SHAPES_OFFSET)));
    m_bottleShape = bottleShape;

    m_bottleMass = 0.03f;

    // creating sword :
    m_swordMeshes = Loader::loadMesh("sword.obj");
    for(Mesh* m : m_swordMeshes)
        m->initGL();

    btCompoundShape* swordShape = new btCompoundShape();

    btVector3 guardBox = btVector3(0.03 + PHYSICS_SHAPES_OFFSET, 0.04 + PHYSICS_SHAPES_OFFSET, 0.25 + PHYSICS_SHAPES_OFFSET);
    swordShape->addChildShape(btTransform::getIdentity(), new btBoxShape(guardBox));

    btTransform bladeTransform = btTransform::getIdentity();
    bladeTransform.setOrigin(btVector3(0.f, 0.486705f, 0.f));
    swordShape->addChildShape(bladeTransform, new btConeShape(0.07 + PHYSICS_SHAPES_OFFSET, 2.15 + PHYSICS_SHAPES_OFFSET));

    m_swordShape = swordShape;
    m_swordMass = 0.5f;
}

void Potator::throwShield()
{
    glm::vec3 pos(0, 10, 0);
    glm::vec3 dir(0, 1, 0);
    if(m_player != nullptr)
    {
        dir = m_player->getDirection();
        pos = m_player->getEyePosition() + dir*2.f;
    }
    float throwForce = 5.f;

    GraphicalContainerNode *node = new GraphicalContainerNode();
    for(Mesh * m : m_shieldMeshes)
        node->addChild(new MeshNode(m));
    createGib(node, m_shieldShape, m_shieldMass, pos, dir*throwForce, 30000);
}

void Potator::throwBottle()
{
    glm::vec3 pos(0, 10, 0);
    glm::vec3 dir(0, 1, 0);
    if(m_player != nullptr)
    {
        dir = m_player->getDirection();
        pos = m_player->getEyePosition() + dir*2.f;
    }
    float throwForce = 5.f;

    GraphicalContainerNode *node = new GraphicalContainerNode();
    for(Mesh * m : m_bottleMeshes)
        node->addChild(new MeshNode(m));
    createGib(node, m_bottleShape, m_bottleMass, pos, dir*throwForce, 30000);
}

void Potator::throwSword()
{
    glm::vec3 pos(0, 10, 0);
    glm::vec3 dir(0, 1, 0);
    if(m_player != nullptr)
    {
        dir = m_player->getDirection();
        pos = m_player->getEyePosition() + dir*2.f;
    }
    float throwForce = 5.f;

    GraphicalContainerNode *node = new GraphicalContainerNode();
    for(Mesh * m : m_swordMeshes)
        node->addChild(new MeshNode(m));
    createGib(node, m_swordShape, m_swordMass, pos, dir*throwForce, 30000);
}

void Potator::update()
{
    GibGeneratorNode::update();

    if(getEngine().isMouseGrabbed())
    {
        Input *input = getEngine().getInput();
        for(Action action : input->getActions())
        {
            if(action.action == m_throwShieldAction)
                throwShield();
            else if(action.action == m_throwBottleAction)
                throwBottle();
            else if(action.action == m_throwObjectAction)
                throwSword();
        }
    }
/*
    ImGui::Begin("Potator");
    if(ImGui::Button("Load pack"))
        LoadingThread::get()->loadResourcePack("woodbox");
    if(ImGui::Button("apply textures"))
    {
        PBRMaterial* mat = dynamic_cast<PBRMaterial*>(m_cubeMesh->getMaterial());
        mat->setTexture(PBRMaterial::ALBEDO_SLOT, RESOURCE_GET(Texture, "woodbox albedo"));
        mat->setTexture(PBRMaterial::METALLIC_SLOT, RESOURCE_GET(Texture, "woodbox metallic"));
        mat->setTexture(PBRMaterial::ROUGHNESS_SLOT, RESOURCE_GET(Texture, "woodbox roughness"));
        mat->setTexture(PBRMaterial::NORMALS_SLOT, RESOURCE_GET(Texture, "woodbox normals"));
        m_scene->registerMeshType(m_cubeMesh->getFlags());
    }
    ImGui::End();
    */
}
