// Copyright (c) 2014 CNRS
// Author: Florent Lamiraux
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
// DAMAGE.

#ifndef HPP_MANIPULATION_CORBA_PROBLEM_IDL
#define HPP_MANIPULATION_CORBA_PROBLEM_IDL

#include <hpp/corbaserver/manipulation/gcommon.idl>
#include <hpp/common.idl>

#include <hpp/pinocchio_idl/robots.idl>
#include <hpp/core_idl/path_planners.idl>
#include <hpp/core_idl/distances.idl>

#include <hpp/manipulation_idl/_path_planners.idl>
#include <hpp/manipulation_idl/_graph.idl>

module hpp {
  module corbaserver {
    module manipulation {
      interface Problem
      {
        /// Select a problem by its name.
        /// If no problem with this name exists, a new
        /// hpp::manipulation::ProblemSolver is created and selected.
        /// \param name the problem name.
        /// \return true if a new problem was created.
        boolean selectProblem (in string name) raises (Error);

        /// Reset the current problem.
        void resetProblem () raises (Error);

        /// Return a list of available elements of type type
        /// \param type enter "type" to know what types I know of.
        ///             This is case insensitive.
        Names_t getAvailable (in string type) raises (Error);

        /// Return a list of selected elements of type type
        /// \param type enter "type" to know what types I know of.
        ///             This is case insensitive.
        /// \note For most of the types, the list will contain only one element.
        Names_t getSelected (in string type) raises (Error);

        /// Load a roadmap from a file
        /// \param filename name of the file from which the roadmap is read.
        void loadRoadmap (in string filename) raises (Error);

        /// Create grasp constraints between robot gripper and object handle
	///
	/// Creates two contraints between a handle and a gripper.
	/// \li The first constraint named "${graspName}" is defined by
	/// the type of handle. For instance, an axial handle defines
	/// a five degree of freedom constraint with free rotation
	/// around the x-axis.
	/// \li the second constraint named "${graspName}/complement" is
	/// the complement to the fully constraint
	/// transformation. For the axial handle, it corresponds to
	/// the rotation around x.
	///
	/// \param graspName prefix of the constraint names for storing in
	///        ProblemSolver map,
	/// \param gripperName name of the gripper used when it has been created
	/// \param handleName name of the handle in the form "object/handle"
	/// where object is the name of the object owning the handle and handle
	/// is the name of the handle in this object.
	/// \sa hpp::manipulation::Handle::createGrasp
	void createGrasp (in string graspName, in string gripperName,
			  in string handleName)
	  raises (Error);

	///Create pre-grasp constraints between robot gripper and object handle
	///
	/// Creates two contraints between a handle and a gripper.
	/// \li The first constraint named "${name}" is the same as
	/// the grasp defined in createGrasp, except that the
	/// translation along x is not constrained. For instance, an
	/// axial handle defines a four degree of freedom constraint
	/// with free rotation and translation around/along the
	/// x-axis,
	/// \li the second constraint named "${name}/double_ineq" is a
	/// double inequality on the relative x-position of the handle
	/// and of the gripper.  the bounds of the inequality are for
	/// now [-.001 c, 2.001 c].
	///
	/// \param name prefix of the constraint names for storing in
	///        ProblemSolver map,
	/// \param gripper name of the gripper used when it has been created
	/// \param handle name of the handle in the form "object/handle"
	/// where object is the name of the object owning the handle and handle
	/// is the name of the handle in this object,
	void createPreGrasp (in string name, in string gripper,
			     in string handle) raises (Error);

        /// Get names of environment contact surfaces
        /// \sa class hpp::core::Shape_t
        /// \note they are also accessible with getAvailable("EnvContact").
        Names_t getEnvironmentContactNames ()
          raises (Error);

        /// Get names of environment contact surfaces on robot
        /// \sa class hpp::core::Shape_t
        /// \note those are also accessible with getAvailable("RobotContact").
        Names_t getRobotContactNames ()
          raises (Error);

        /// Get environment contact from name
        ///
        /// A contact surface may be composed of several convex polygons.
        /// Let us denote by n the number of polygons.
        /// \param name name of the contact surface
        /// \return a list of n times the same joint name
        /// \retval indices sequence of n numbers of vertices one for each
        ///         polygon,
        /// \retval points sequence of vertices. The number should be the
        ///         sum of the elements of indices.
        Names_t getEnvironmentContact (in string name, out intSeq indices,
                                       out floatSeqSeq points)
          raises (Error);

        /// Get robot contact from name
        ///
        /// A contact surface may be composed of several convex polygons.
        /// Let us denote by n the number of polygons.
        /// \param name name of the contact surface
        /// \return a list of n times the same joint name
        /// \retval indices sequence of n numbers of vertices one for each
        ///         polygon,
        /// \retval points sequence of vertices. The number should be the
        ///         sum of the elements of indices.
        Names_t getRobotContact (in string name, out intSeq indexes,
                                 out floatSeqSeq points)
          raises (Error);

	/// Create a placement constraint between a shapes of robot and env.
	///
	/// \param placementName Name of the numerical constraint,
	/// \param shapeName List of names of the list of shapes as stored in the
	///        Device instance,
	/// \param envContactName list of names of the list of shapes as stored in
	///        ProblemSolver instance
	///
	/// A placement constraint specifies that surfaces delimited by
	/// one shape of the robot and one shape of the environment
	/// should have an intersection of positive area.
        void createPlacementConstraint (in string placementName,
            in Names_t shapeName, in Names_t envContactName)
          raises (Error);

	/// Create a pre-placement constraint between a shapes of robot and env.
	///
	/// \param placementName Name of the numerical constraint,
	/// \param shapeName Name of the list of shapes as stored in the
	///        Device instance,
	/// \param envContactName Name of the list of shapes as stored in
	///        ProblemSolver instance
	/// \param width the approaching distance.
	///
	/// A pre-placement constraint specifies that surfaces delimited by
	/// one shape of the robot and one shape of the environment
	/// should have an intersection of positive area.
        void createPrePlacementConstraint (in string placementName,
            in Names_t shapeName, in Names_t envContactName, in double witdh)
          raises (Error);

        /// Create a QPStaticStability constraints
        /// \param constraintName
        /// \param comRootJointName name of the root joint of the center of
        ///        mass to be used,
        /// \param shapesName list of the convex shape name of the robot on
        ///        which forces are applied.
        ///
        void createQPStabilityConstraint(in string constraintName,
            in string comRootJointName, in Names_t shapesName)
          raises (Error);

        /// Set the problem constraints to the specified constraint.
        ///
        /// \param idComp ID of a node or a configuration
        /// \param target: ignored for states. For edges:
        ///        \li true: uses the edge target constraint
        ///        \li false: uses the edge path constraint
        boolean setConstraints (in ID idComp, in boolean target)
          raises (Error);

        /// Register constraints
        /// \param constraint a numerical constraint partially constraining the
        ///        (relative) pose of an object or robot body (grasp,
        ///        placement),
        /// \param complement the complement constraint, i.e. the constaint that
        ///        combined with the previous one totally constrains the pose
        ///        of the object or robot body.
        /// \param both a constraint (usually explicit) that is equivalent to
        ///        the combination of the two first parameters.
        ///
        /// Registering constraints enables the numerical solvers to be more
        /// efficient. Instead of inserting "constraint" and "complement" in
        /// a solver, the graph will insert constraint "both", thus replacing
        /// two implicit constraints by an explicit one.
        void registerConstraints(in string constraint, in string complement,
                                 in string both);

        /// Apply constaints to a configuration
        ///
        /// \param idComp ID of a node or a configuration
        /// \param input input configuration,
        /// \retval output output configuration,
        /// \retval error norm of the residual error.
        /// \deprecated Use Graph::applyNodeConstraints instead
        boolean applyConstraints (in ID idComp, in floatSeq input, out floatSeq output,
            out double residualError)
          raises (Error);

        /// Apply constaints to a configuration
        ///
        /// \param IDedge ID of an edge
        /// \param qnear configuration to initiliaze the projector,
        /// \param input input configuration,
        /// \retval output output configuration,
        /// \retval error norm of the residual error.
	///
	/// Call method using hpp::manipulation::graph::Edge::applyConstraints.
        /// \deprecated Use Graph::generateTargetConfig instead.
        boolean applyConstraintsWithOffset (in ID IDedge, in floatSeq qnear, in floatSeq input, out floatSeq output,
            out double residualError)
          raises (Error);

        /// Build a path from qb to qe using the Edge::build.
        /// \param IDedge id of the edge to use.
        /// \param qb configuration at the beginning of the path
        /// \param qe configuration at the end of the path
        /// \retval return true if the path is built and fully projected.
        /// \retval indexNotProj -1 is the path could not be built. The index
        ///                      of the built path (before projection) in the
        ///                      in the ProblemSolver path vector.
        /// \retval indexProj -1 is the path could not be fully projected. The
        ///                   index of the built path (before projection) in the
        ///                   in the ProblemSolver path vector.
        /// No path validation is made. The paths can be retrieved using
        /// corbaserver::Problem::configAtParam
        boolean buildAndProjectPath (in ID IDedge, in floatSeq qb, in floatSeq qe, out long indexNotProj,
            out long indexProj)
          raises (Error);

        /// Set a state of the constraint graph as target of the problem.
        /// \warning when setTargetState is called, goal configurations are
        ///          ignored.
        void setTargetState(in ID IDstate) raises (Error);

        /// Get the edge ID of the motion that generated the configuration
        /// at the given parameter.
        ID edgeAtParam (in unsigned long inPathId, in double atDistance, out string graphName)
          raises (Error);

        manipulation_idl::graph_idl::Validation createGraphValidation ()
          raises (Error);

	/// Read a roadmap from a file
	/// \param filename name of the file,
        ///        If it ends with '.xml', then the file is interpreted in
        ///        XML format, otherwise it is interpreted in binary format.
	/// \param robot the robot for which the roadmap was built before
	///        saving in the file,
	/// \param constraint graph with which the roadmap was build before
	///        saving in the file.
	/// \return the roadmap as a CORBA object.
        core_idl::Roadmap readRoadmap(in string filename, in pinocchio_idl::Device robot,
          in manipulation_idl::graph_idl::Graph graph) raises (Error);

	/// Write a roadmap ro a file
	/// \param filename name of the file,
        ///        If it ends with '.xml', then the file is interpreted in
        ///        XML format, otherwise it is interpreted in binary format.
	/// \param robot the robot for which the roadmap was built before
	///        saving in the file,
	/// \param constraint graph with which the roadmap was build before
	///        saving in the file.
	/// \return the roadmap as a CORBA object.
        void writeRoadmap(in string filename, in core_idl::Roadmap roadmap,
          in pinocchio_idl::Device robot,
          in manipulation_idl::graph_idl::Graph graph) raises (Error);

        core_idl::Roadmap createRoadmap(in core_idl::Distance distance,
          in pinocchio_idl::Device robot) raises (Error);
        /// Create a Transition Planner
        core_idl::PathPlanner createTransitionPlanner() raises(Error);
      }; // interface Problem
    }; // module manipulation
  }; // module corbaserver
}; // module hpp

#endif // HPP_MANIPULATION_CORBA_ROBOT_IDL
