/*
 * FloorFactory.cpp
 *
 *  Created on: Aug 12, 2019
 *      Author: fredrick
 */

#include "FloorFactory.h"

namespace JamSpook {

FloorFactory::FloorFactory(weak_ptr<AssetSystem> assetSystem,
                         weak_ptr<GraphicsSystem> graphicsSystem,
                         weak_ptr<PhysicsSystem> physicsSystem,
                         weak_ptr<RenderLayer> renderLayer):
        mAssetSystem(assetSystem),
        mGraphicsSystem(graphicsSystem),
        mPhysicsSystem(physicsSystem),
        mRenderLayer(renderLayer)
{}

FloorFactory::~FloorFactory()
{}

shared_ptr<Entity> FloorFactory::createFloor(const vec3 position)
{
    // Create instance
    shared_ptr<Entity> entity = make_shared<Entity>();
    entity->setEntityTag("floor");
    SceneGraph::addEntity(entity);
    mat4 transform = translate(mat4(1), position);

    // Add physics component
    ColliderFactory* colliderFactory = new ColliderFactory(mPhysicsSystem);
    shared_ptr<FloorPhysicsComponent> physicsComponent =
            make_shared<FloorPhysicsComponent>(
                    transform,
                    entity,
                    getShared(mPhysicsSystem),
                    getShared(mPhysicsSystem),
                    getShared(mPhysicsSystem),
                    colliderFactory->createBoxCollider(position,
                                                       quat(vec3(0,0,0)),
                                                       vec3(10,1,10), // radius
                                                       100.0f, // mass
                                                       entity,
                                                       entity->getEntityTag()));
    delete colliderFactory;
    // Note: Editing of rigid body params, maybe only has effect is it has been added to the world.
    physicsComponent->getCollider()->getRigidBody()->setLinearFactor(btVector3(0,1,0));  // allow all positional movement movement
    physicsComponent->getCollider()->getRigidBody()->setAngularFactor(btVector3(1,1,1)); // allow all rotational movement movement
    physicsComponent->getCollider()->getRigidBody()->setRestitution(1);
    entity->addComponent(physicsComponent);


    // Add graphics component
    shared_ptr<GraphicsComponent> graphicsComponent = make_shared<GraphicsComponent>(transform,
                                                                                     entity,
                                                                                     getShared(mGraphicsSystem),
                                                                                     mRenderLayer);
    entity->addComponent(graphicsComponent);

    // Add the ModelRenderable of a ball
    ModelRenderableFactory* modelFactory = new ModelRenderableFactory(mAssetSystem);
    shared_ptr<ModelRenderable> modelRenderable = modelFactory->createModel("floor.f3d",
                                                                            "floor.png",
                                                                            "floor-model");
    delete modelFactory;
    graphicsComponent->addRenderable(modelRenderable);

//    // Add ICC response component for the collectable system
//    weak_ptr<Entity> wEntity = entity;
//    entity->addComponent(make_shared<ICCResponseComponent>(entity, [this, wEntity](shared_ptr<Message> message){
//        if (message->getMessageType() == IDCache::get("CollectedMessage"))
//        {
//            shared_ptr<Entity> entity = dynamic_pointer_cast<Entity>(getShared(wEntity));
//            if (entity->getEntityTag() == "pellet")
//            {
//                Log::write(LogLevel::debug, "collected pellet!");
//            }
//        }
//    }));

    // Return instance
    return entity;
}

shared_ptr<Entity> FloorFactory::createStaticFloor(const vec3 position)
{
    // Create instance
    shared_ptr<Entity> entity = make_shared<Entity>();
    entity->setEntityTag("floor");
    SceneGraph::addEntity(entity);
    mat4 transform = translate(mat4(1), position);

    // Add physics component
    ColliderFactory* colliderFactory = new ColliderFactory(mPhysicsSystem);
    shared_ptr<FloorPhysicsComponent> physicsComponent =
            make_shared<FloorPhysicsComponent>(
                    transform,
                    entity,
                    getShared(mPhysicsSystem),
                    getShared(mPhysicsSystem),
                    getShared(mPhysicsSystem),
                    colliderFactory->createBoxCollider(position,
                                                       quat(vec3(0,0,0)),
                                                       vec3(10,1,10), // radius
                                                       0.0f, // mass
                                                       entity,
                                                       entity->getEntityTag()));
    delete colliderFactory;
    // Note: Editing of rigid body params, maybe only has effect is it has been added to the world.
    physicsComponent->getCollider()->getRigidBody()->setLinearFactor(btVector3(0,0,0));  // allow all positional movement movement
    physicsComponent->getCollider()->getRigidBody()->setAngularFactor(btVector3(0,0,0)); // allow all rotational movement movement
    physicsComponent->getCollider()->getRigidBody()->setRestitution(0.9f);
    entity->addComponent(physicsComponent);


    // Add graphics component
//    shared_ptr<GraphicsComponent> graphicsComponent = make_shared<GraphicsComponent>(transform,
//                                                                                     entity,
//                                                                                     getShared(mGraphicsSystem),
//                                                                                     mRenderLayer);
//    graphicsComponent->setScale(vec3(2.0f, 1.0f, 2.0f));
//    entity->addComponent(graphicsComponent);

//    // Add the ModelRenderable of a ball
//    ModelFactory* modelFactory = new ModelFactory(mAssetSystem);
//    shared_ptr<ModelRenderable> modelRenderable = modelFactory->createModel("floor.f3d",
//                                                                            "floor.png",
//                                                                            "floor-model");
//    delete modelFactory;
//    graphicsComponent->addRenderable(modelRenderable);

    // Return instance
    return entity;
}

} // namespace JamSpook
