// This file is a part of the OpenSurgSim project.
// Copyright 2013, SimQuest Solutions Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef SURGSIM_PHYSICS_CONTACTCONSTRAINTGENERATION_H
#define SURGSIM_PHYSICS_CONTACTCONSTRAINTGENERATION_H

#include  <memory>

#include "SurgSim/Framework/Macros.h"
#include "SurgSim/Physics/Computation.h"


namespace SurgSim
{

namespace Framework
{
class Logger;
}

namespace DataStructures
{
struct Location;
}
namespace Collision
{
class Representation;
}

namespace Physics
{

class Localization;
class PhysicsManagerState;
class Representation;

/// Generate a constraint for every contact that was calculated.
/// The general algorithm is such, for each pair of Collision Representations that has Contacts
/// For each contact:
/// - Generate a localization for each side of the pair
/// - Find the correct CollisionImplementation for the Representation and type of constraint, note that currently
///   we use only one type of constraint for the collision
/// - Create the ConstraintData for the contact with
/// - Create a constraint from, the ContactImplmentation, Localization and ConstraintData
/// - Add it to the list of Constraints
/// At the end those constraints are added as contact constraints to the physics state
class ContactConstraintGeneration : public Computation
{
public:
	/// Constructor
	/// \param doCopyState Specify if the output state in Computation::Update() is a copy or not of the input state
	explicit ContactConstraintGeneration(bool doCopyState = false);

	SURGSIM_CLASSNAME(SurgSim::Physics::ContactConstraintGeneration);

	/// Destructor
	~ContactConstraintGeneration();

private:
	/// The logger for this class
	std::shared_ptr<SurgSim::Framework::Logger> m_logger;

	/// Overridden function from Computation, the actual work is done here
	/// \param	dt		The time passed from the last update in seconds.
	/// \param	state	The physics state.
	/// \return	The changed state of the, depending on the setting of doCopyState this is either the same instance
	/// 		or a copied instance of the physics state.
	std::shared_ptr<PhysicsManagerState> doUpdate(const double& dt, const std::shared_ptr<PhysicsManagerState>& state)
		override;

	/// Generate a location from a Collision Representation.
	/// \param	physicsRepresentation	The physics representation.
	/// \param	collisionRepresentation	The collision representation.
	/// \param	location				The location generated by the contact calculation.
	/// \return	The localization for the collision representations physics representation.
	/// \note Asserts if cannot Location create shared object.
	std::shared_ptr<SurgSim::DataStructures::Location> makeLocation(
		std::shared_ptr<SurgSim::Physics::Representation> physicsRepresentation,
		std::shared_ptr<SurgSim::Collision::Representation> collisionRepresentation,
		const SurgSim::DataStructures::Location& location);
};

}; // Physics
}; // SurgSim

#endif
