#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 "tools/loader.h"
#include "tools/loadingthread.h"
#include "SparrowRenderer/texture.h"
#include "scene/scenenode.h"
#include "resourcemanager.h"
#include <imgui/imgui.h>

#define PHYSICS_SHAPES_OFFSET 0.0025f
/*
class GibScript : public SceneNode::Script
{
    GibScript(const std::string &modelPath, btCollisionShape* shape, float mass) :
        m_shape(shape),
        m_mass(mass)
    {
        // preload model
        Loader::loadMesh(modelPath);
    }

    void begin(SceneNode* node)
    {
        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;

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

    void update(SceneNode* node)
    {

    }

private:
    std::vector<Mesh*> m_meshes;
    btCollisionShape* m_shape;
    float m_mass;
    int m_action;
};

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)
{
    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_shieldScript = new GibScript("shield.obj", shieldShape, 0.5f);

    // creating bottle
    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_bottleScript = new GibScript("bottle.obj", bottleShape, 0.5f);

    // creating sword :
    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_swordScript = new GibScript("sword.obj", swordShape, 0.03f);
}

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;

    SceneNode *node = new SceneNode();
    for(Mesh * m : m_shieldMeshes)
    {
        SceneNode* meshNode = new SceneNode();
        meshNode->setMesh(m);
        node->addChild(meshNode);
    }
    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;

    SceneNode *node = new SceneNode();
    for(Mesh * m : m_bottleMeshes)
    {
        SceneNode* meshNode = new SceneNode();
        meshNode->setMesh(m);
        node->addChild(meshNode);
    }
    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;

    SceneNode *node = new SceneNode();
    for(Mesh * m : m_swordMeshes)
    {
        SceneNode* meshNode = new SceneNode();
        meshNode->setMesh(m);
        node->addChild(meshNode);
    }
    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();
}
*/
