/*
 * BallFactory.cpp
 *
 *  Created on: Aug 9, 2019
 *      Author: fredrick
 */

#include "BallFactory.h"

namespace JamSpook {

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

BallFactory::~BallFactory()
{}

shared_ptr<Entity> BallFactory::createBall(const vec3 position,
                                           const float radius,
                                           const float mass,
                                           const float restitution,
                                           const string& name,
                                           const vec3 lightColor)
{
    // Create instance
    shared_ptr<Entity> entity = make_shared<Entity>();
    entity->setEntityTag(name + "_ball");
    SceneGraph::addEntity(entity);
    mat4 transform = translate(mat4(1), position);

    // Add physics component
    ColliderFactory* colliderFactory = new ColliderFactory(mPhysicsSystem, mAssetSystem);
    shared_ptr<BallPhysicsComponent> physicsComponent =
            make_shared<BallPhysicsComponent>(
                    transform,
                    entity,
                    getShared(mPhysicsSystem),
                    getShared(mPhysicsSystem),
                    getShared(mPhysicsSystem),
                    colliderFactory->createSphereCollider(position,
                                                          quat(vec3(0,0,0)),
                                                          radius, // radius
                                                          mass, // 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(1,1,1));  // allow all positional movement movement
    physicsComponent->getCollider()->getRigidBody()->setAngularFactor(btVector3(1,1,1)); // allow all rotational movement movement
    physicsComponent->getCollider()->getRigidBody()->setRestitution(restitution);
//    physicsComponent->getCollider()->getRigidBody()->setGravity(btVector3(0,-1,0));       // no gravity, length of zero
    physicsComponent->getCollider()->getRigidBody()->setActivationState(DISABLE_DEACTIVATION); // RigidBody may never sleep. (Note: Or else it will not respond to setLinearVelocity when standing still for too long(a couple of seconds).)

    entity->addComponent(physicsComponent);

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

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

    // Add internal pointlight
    LightSourceFactory* lightSourceFactory = new LightSourceFactory(mAssetSystem, mGraphicsSystem);
    shared_ptr<LightSource> lightSource = lightSourceFactory->createPointLight(lightColor,
                                                                               0.02f,
                                                                               0.03f,
                                                                               transform);
    graphicsComponent->setLightSource(lightSource);
    delete lightSourceFactory;

    // Return instance
    return entity;
}

} // namespace JamSpook
