/*
 * TrackPieceFactory.h
 *
 *  Created on: Aug 27, 2020
 *      Author: fredrick
 */

#ifndef ENTITIES_TRACKPIECEFACTORY_H_
#define ENTITIES_TRACKPIECEFACTORY_H_

#include <string>
#include <memory>
#include <functional>
#include <vector>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/euler_angles.hpp>
#include <glm/gtx/string_cast.hpp>
#include <glm/gtx/quaternion.hpp>

#include <ecos/utility/Memory.h>
#include <ecos/core/IDCache.h>
#include <ecos/core/Log.h>
#include <ecos/core/BroadcastObservable.h>
#include <ecos/core/Message.h>
#include <ecos/core/Entity.h>
#include <ecos/core/SceneGraph.h>
#include <ecos/core/ICCResponseComponent.h>
#include <ecos/asset/AssetSystem.h>
#include <ecos/asset/DataManagementMode.h>
#include <ecos/physics/PhysicsSystem.h>
#include <ecos/physics/PhysicsComponent.h>
#include <ecos/physics/ColliderFactory.h>
#include <ecos/physics/Collider.h>
#include <ecos/graphics/GraphicsSystem.h>
#include <ecos/graphics/GraphicsComponent.h>
#include <ecos/graphics/RenderLayer.h>
#include <ecos/graphics/TextureFactory.h>
#include <ecos/graphics/Texture.h>
#include <ecos/graphics/assets/ShaderAsset.h>
#include <ecos/graphics/ShaderProgram.h>
#include <ecos/graphics/ShaderProgramFactory.h>
#include <ecos/graphics/Material.h>
#include <ecos/graphics/MaterialFactory.h>
#include <ecos/graphics/Mesh.h>
#include <ecos/graphics/MeshFactory.h>
#include <ecos/graphics/ModelRenderable.h>
#include <ecos/graphics/ModelRenderableFactory.h>
#include <ecos/graphics/ShaderType.h>

#include "TrackPiecePhysicsComponent.h"

namespace JamSpook {

using std::string;
using std::shared_ptr;
using std::make_shared;
using std::weak_ptr;
using std::dynamic_pointer_cast;
using std::function;
using std::bind;
using std::vector;

using glm::vec3;
using glm::mat4;
using glm::quat;
using glm::quat_cast;
using glm::translate;
using glm::scale;
using glm::rotate;
using glm::eulerAngleXYZ;
using glm::radians;

using ecos::utility::getShared;

using ecos::core::IDCache;
using ecos::core::logging::Log;
using ecos::core::logging::LogLevel;
using ecos::core::BroadcastObservable;
using ecos::core::Message;
using ecos::core::Entity;
using ecos::core::SceneGraph;
using ecos::core::ICCResponseComponent;

using ecos::asset::AssetSystem;
using ecos::asset::DataManagementMode;

using ecos::graphics::GraphicsSystem;
using ecos::graphics::GraphicsComponent;
using ecos::graphics::RenderLayer;
using ecos::graphics::TextureFactory;
using ecos::graphics::Texture;
using ecos::graphics::ShaderType;
using ecos::graphics::ShaderAsset;
using ecos::graphics::ShaderProgram;
using ecos::graphics::ShaderProgramFactory;
using ecos::graphics::Material;
using ecos::graphics::MaterialFactory;
using ecos::graphics::Mesh;
using ecos::graphics::MeshFactory;
using ecos::graphics::ModelRenderableFactory;
using ecos::graphics::ModelRenderable;

using ecos::physics::PhysicsSystem;
using ecos::physics::PhysicsComponent;
using ecos::physics::ColliderFactory;
using ecos::physics::Collider;

/// Factory to simplify track piece entity creation
class TrackPieceFactory
{
private:
    weak_ptr<AssetSystem>    mAssetSystem;
    weak_ptr<GraphicsSystem> mGraphicsSystem;
    weak_ptr<PhysicsSystem>  mPhysicsSystem;
    weak_ptr<RenderLayer>    mRenderLayer;

public:
    TrackPieceFactory(weak_ptr<AssetSystem>    assetSystem,
                      weak_ptr<GraphicsSystem> graphicsSystem,
                      weak_ptr<PhysicsSystem>  physicsSystem,
                      weak_ptr<RenderLayer>    renderLayer);
    virtual ~TrackPieceFactory();

    /// Compose a road entity
    shared_ptr<Entity> createRoad();

    /// Compose a tunnel entity
    shared_ptr<Entity> createTunnel();

//    /// Compose a tunnel entity
//    shared_ptr<Entity> createTunnel();

    /// Compose a mountain entity
    shared_ptr<Entity> createMountain();

    /// Compose a sign entity
    shared_ptr<Entity> createSign(const string name,
                                  const string diffuseTextureFilePath,
                                  vec3 position,
                                  quat orientation);

    /// Compose a ghost entity
    shared_ptr<Entity> createGhost(const string name,
                                   const string diffuseTextureFilePath,
                                   vec3 position,
                                   quat orientation,
                                   float scaling = 1.0f);

    shared_ptr<Entity> createStaticPlatform();
};

} // namespace JamSpook

#endif // ENTITIES_TRACKPIECEFACTORY_H_
