/*
 * LightingFactory.cpp
 *
 *  Created on: Sep 26, 2019
 *      Author: fredrick
 */

#include "LightingFactory.h"

namespace JamSpook {

LightingFactory::LightingFactory(weak_ptr<AssetSystem> assetSystem,
                                 weak_ptr<GraphicsSystem> graphicsSystem,
                                 weak_ptr<PhysicsSystem> physicsSystem,
                                 weak_ptr<InteractionSystem> interactionSystem):
        mAssetSystem(assetSystem),
        mGraphicsSystem(graphicsSystem),
        mPhysicsSystem(physicsSystem),
        mInteractionSystem(interactionSystem)
{}

LightingFactory::~LightingFactory()
{}

shared_ptr<Entity> LightingFactory::createPointLight(const vec3 position,
                                                     const vec3 color,
                                                     const float intensity,
                                                     weak_ptr<RenderLayer> renderLayer)
{
    // Create instance
    shared_ptr<Entity> entity = make_shared<Entity>();
    entity->setEntityTag("pointLight");
    SceneGraph::addEntity(entity);
    mat4 transform = translate(mat4(1), position);

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

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

    // Return instance
    return entity;
}

shared_ptr<Entity> LightingFactory::createSun(const float distance,
                             const vec3 eulerRotationXYZDegrees,
                             const vec3 color,
                             const float intensity,
                             weak_ptr<RenderLayer> renderLayer)
{
    // Create instance
    shared_ptr<Entity> entity = make_shared<Entity>();
    entity->setEntityTag("directionalLight");
    SceneGraph::addEntity(entity);

    mat4 rotateToCenter = eulerAngleXYZ(radians(static_cast<float>(-90)),
                                        radians(static_cast<float>(0)),
                                        radians(static_cast<float>(0)));

    mat4 rotation = eulerAngleXYZ(radians(static_cast<float>(eulerRotationXYZDegrees.x)),
            radians(static_cast<float>(eulerRotationXYZDegrees.y)),
            radians(static_cast<float>(eulerRotationXYZDegrees.z)));

    mat4 translation = translate(mat4(1.0f), vec3(0,distance,0));



//    mat4 transform = rotation * rotateToCenter * translation;
    mat4 transform = rotation * translation * rotateToCenter;

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

    // Add light source
    LightSourceFactory* lightSourceFactory = new LightSourceFactory(mAssetSystem, mGraphicsSystem);
    shared_ptr<LightSource> lightSource = lightSourceFactory->createDirectionalLight(color,
                                                                                     intensity,
                                                                                     0.0f,
                                                                                     true,
                                                                                     transform);
    graphicsComponent->setLightSource(lightSource);
    delete lightSourceFactory;

    // Return instance
    return entity;
}

shared_ptr<Entity> LightingFactory::createDirectionalLight(const vec3 position,
                                                           const vec3 eulerRotationXYZDegrees,
                                                           const vec3 color,
                                                           const float intensity,
                                                           weak_ptr<RenderLayer> renderLayer)
{
    // Create instance
    shared_ptr<Entity> entity = make_shared<Entity>();
    entity->setEntityTag("directionalLight");
    SceneGraph::addEntity(entity);
//    mat4 transform = translate(mat4(1), position);
//    mat4 transform =  glm::lookAt(vec3(0,1,0), vec3(0,-1,0), vec3(0,0,-1));
//    mat4 transform = translate(mat4(1.0f), position) * rotate(mat4(1.0f),
//                            radians(-90.0f),
//                            vec3(1.0f, 0.0f, 0.0f))
//                     ;

    mat4 transform = translate(mat4(1.0f), position) *
                     eulerAngleXYZ(radians(static_cast<float>(eulerRotationXYZDegrees.x)),
                                   radians(static_cast<float>(eulerRotationXYZDegrees.y)),
                                   radians(static_cast<float>(eulerRotationXYZDegrees.z)));

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

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

    // Add light source
    LightSourceFactory* lightSourceFactory = new LightSourceFactory(mAssetSystem, mGraphicsSystem);
    shared_ptr<LightSource> lightSource = lightSourceFactory->createDirectionalLight(color,
                                                                                     intensity,
                                                                                     0.0f,
                                                                                     false,
                                                                                     transform);
    graphicsComponent->setLightSource(lightSource);
    delete lightSourceFactory;
//
//    // Add interaction component
//    shared_ptr<LightInteractionComponent> interactionComponent =
//            make_shared<LightInteractionComponent>(transform,
//                                                   entity,
//                                                   getShared(mInteractionSystem));
//    entity->addComponent(interactionComponent);

//    // Add physics component
//    ColliderFactory* colliderFactory = new ColliderFactory(mPhysicsSystem);
//    shared_ptr<LightPhysicsComponent> physicsComponent =
//            make_shared<LightPhysicsComponent>(
//                    transform,
//                    entity,
//                    getShared(mPhysicsSystem),
//                    getShared(mPhysicsSystem),
//                    getShared(mPhysicsSystem),
//                    colliderFactory->createSphereCollider(position,
//                                                          quat(vec3(0,0,0)),
//                                                          .5f, // radius
//                                                          0.0, // 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(.9f);
//    physicsComponent->getCollider()->getRigidBody()->setActivationState(DISABLE_DEACTIVATION);
//
//    entity->addComponent(physicsComponent);

    // Return instance
    return entity;
}

} // namespace JamSpook
