/*
 * This file is part of ArmarX.
 *
 * ArmarX is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * ArmarX is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * @package    RobotAPI::ArmarXObjects::TCPControllerSubUnit
 * @author     Stefan Reither ( stef dot reither at web dot de )
 * @date       2017
 * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
 *             GNU General Public License
 */

#pragma once

#include <RobotAPI/interface/units/TCPControlUnit.h>

#include "RobotUnitSubUnit.h"
#include "../NJointControllers/NJointTCPController.h"
#include "../util.h"

#include <ArmarXCore/core/Component.h>

#include <mutex>

namespace armarx
{
    TYPEDEF_PTRS_HANDLE(RobotUnit);
    class TCPControllerSubUnitPropertyDefinitions : public armarx::ComponentPropertyDefinitions
    {
    public:
        TCPControllerSubUnitPropertyDefinitions(std::string prefix):
            armarx::ComponentPropertyDefinitions(prefix)
        {
            defineOptionalProperty<float>("AvoidJointLimitsKp", 1.f, "Proportional gain value of P-Controller for joint limit avoidance", PropertyDefinitionBase::eModifiable);
        }
    };

    TYPEDEF_PTRS_HANDLE(TCPControllerSubUnit);
    class TCPControllerSubUnit :
        virtual public RobotUnitSubUnit,
        virtual public TCPControlUnitInterface,
        virtual public Component
    {
    public:
        void setup(RobotUnit* rUnit, VirtualRobot::RobotPtr robot);

        // TCPControlUnitInterface interface
        void setCycleTime(Ice::Int milliseconds, const Ice::Current& c = Ice::emptyCurrent) override;
        void setTCPVelocity(const std::string& nodeSetName, const std::string& tcpName, const::armarx::FramedDirectionBasePtr& translationVelocity, const::armarx::FramedDirectionBasePtr& orientationVelocityRPY, const Ice::Current& c = Ice::emptyCurrent) override;
        bool isRequested(const Ice::Current& = Ice::emptyCurrent) override;

        // RobotUnitSubUnit interface
        void update(const SensorAndControl& sc, const JointAndNJointControllers& c) override;
    private:
        mutable std::mutex dataMutex;
        RobotUnit* robotUnit = nullptr;
        VirtualRobot::RobotPtr coordinateTransformationRobot;
        std::map<std::string, std::string> tcpControllerNameMap;

        // ManagedIceObject interface
    protected:
        void onInitComponent() override {}
        void onConnectComponent() override {}
        std::string getDefaultName() const override
        {
            return "TCPControlUnit";
        }


        PropertyDefinitionsPtr createPropertyDefinitions() override;

        // UnitResourceManagementInterface interface
    public:
        void request(const Ice::Current&) override
        {
        }
        void release(const Ice::Current&) override
        {
        }

        // UnitExecutionManagementInterface interface
    public:
        void init(const Ice::Current&) override {}
        void start(const Ice::Current&) override {}
        void stop(const Ice::Current&) override {}
        UnitExecutionState getExecutionState(const Ice::Current&) override
        {
            return UnitExecutionState::eUndefinedUnitExecutionState;
        }

        // KinematicUnitListener interface
    public:
        void reportControlModeChanged(const NameControlModeMap&, Ice::Long, bool, const Ice::Current&) override {}
        void reportJointAngles(const NameValueMap&, Ice::Long, bool, const Ice::Current&) override {}
        void reportJointVelocities(const NameValueMap&, Ice::Long, bool, const Ice::Current&) override {}
        void reportJointTorques(const NameValueMap&, Ice::Long, bool, const Ice::Current&) override {}
        void reportJointAccelerations(const NameValueMap&, Ice::Long, bool, const Ice::Current&) override {}
        void reportJointCurrents(const NameValueMap&, Ice::Long, bool, const Ice::Current&) override {}
        void reportJointMotorTemperatures(const NameValueMap&, Ice::Long, bool, const Ice::Current&) override {}
        void reportJointStatuses(const NameStatusMap&, Ice::Long, bool, const Ice::Current&) override {}

        // PropertyUser interface
    public:
        void componentPropertiesUpdated(const std::set<std::string>& changedProperties) override;
    };
}