#include <config.h>
#include <Nice/App/Application.h>
#include <Nice/App/ConfigClient.h>

#include <Basda/Mocca/WheelServiceWorkerInterface.h>
#include <Basda/Mocca/Exception.h>
#include <Basda/Mocca/Constant.h>
#include <boost/assign/list_inserter.hpp>

using namespace std;
using namespace Ice;
using namespace boost::assign;

class MoccaIfTester: public Nice::Application
{
    public:
        virtual int usage(int);
        virtual int run(int argc, char* argv[]);
        virtual void interruptCallback(int _sig);

};

int MoccaIfTester::usage(int _ret)
{
    cerr << "Usage: " << appName() << " --CONFIG:Endpoint=[..]\n";
    cerr
            << "Options:\n"
                    "-h, --help                                       Show this message.\n"
                    "-v, --version                                    Display version.\n"
                    "\n"
                    "\n"
                    "--CONFIG:Endpoint=[NAME=NODENAME,...]          NAME=NODENAME  - name of the service\n"
                    "                                                PORT=intval    - tcp port of the service\n"
                    "                                                HOST=string    - tcp host address of the service\n"
                    "                                                MULTICAST=true - resolve service by multicast\n"
                    "\n"
                    "Examples:\n"
                    "\n";
    cerr << appName() << " --CONFIG:Endpoint=[NAME=svc,HOST=host,PORT=4711]\n";
    cerr << appName() << " --CONFIG:Endpoint=[NAME=svc,PORT=4711]\n";
    cerr << appName() << " --CONFIG:Endpoint=[NAME=svc,MULTICAST=1]\n"
            "\n"
            "Hints:\n"
            " Don't put spaces in commandline arguments or use quotes\n"
            " NO: --CONFIG:Endpoint=[NAME=svc, PORT=4711]\n"
            " OK: --CONFIG:Endpoint=\"[NAME=svc, PORT=4711]\"\n"
            "\n"
            "\n";
    return _ret;
}

void MoccaIfTester::interruptCallback(int _sig)
{
    N_LOG( "Interrupt #" << _sig);
}

int MoccaIfTester::run(int /*argc*/, char* /*argv*/[])
{
    int status = 0;
    std::string unit = "STEPS";
    try
    {
        callbackOnInterrupt();

        D_LOG( config()->leaf ( "CONNECT" ));

        // first we connect to the specified service using the CONNECT string which was passed via the command line
        Nice::AppConfigClientPtr con = Nice::AppConfigClient::create(
                config()->getAtNode<Nice::Endpoint>("CONNECT"), config()->node("DATA"));

        // create a variable that points to the motor interface
        Basda::MoccaWheelServiceWorkerInterfacePtr mocca;

        N_LOG("getting NODE");
        Nice::JointPtr node = config()->node("DATA.SCI_WHEEL1.SVC");
        //N_LOG(node);

        // a command interface has to be created for the wheel
//        U3_LOG(" #1 create")
        mocca = Basda::MoccaWheelServiceWorkerInterface::create(node->path());
        //N_LOG(node->path());

        // now we can move all motor to the home position
//        U3_LOG(" #3 moveHome");
//        mocca->moveToHome();
//        I_LOG("isAtHome: " << mocca->isAtHome());

//        U3_LOG(" #4 moveToNamedPosition: 10");
        I_LOG(" ... should work ...");
        mocca->moveToNamedPosition(3);
        N_LOG("position: " << mocca->getPosition(unit));

////        U3_LOG(" #5 moveToNamedPosition: 13");
//        I_LOG(" ... should work ...");
//        mocca->moveToNamedPosition(13);
//        N_LOG("position: " << mocca->getPosition(unit));
//
////        U3_LOG(" #6 moveToNamedPosition: 14");
//        I_LOG(" ... should work ...");
//        mocca->moveToNamedPosition(14);
//        N_LOG("position: " << mocca->getPosition(unit));
//
////        U3_LOG(" #7 moveToNamedPosition: 11");
//        I_LOG(" ... should work ...");
//        mocca->moveToNamedPosition(11);
//        N_LOG("position: " << mocca->getPosition(unit));

        try
        {
//        U3_LOG(" #8 moveToNamedPosition: 22");
            I_LOG(" ... should not work ... but fail ...");
            mocca->moveToNamedPosition(2);
            status = -1;
        }

        catch(const Basda::Svc::MoccaWheelServiceException & _e)
        {
            N_LOG("position: " << mocca->getPosition(unit));
        }

        return status;
    }

    catch (const Basda::Svc::MoccaMotionException &e)
    {
    	I_LOG( "We have a MoccaWheelNotAtPositionSwitchException ... as expected - SUCCESS!");
    	status = 0;
    }

    catch (const Nice::Exception & ex)
    {
    	E_LOG(ex);
    	status = -1;
    }

    catch (const IceUtil::Exception& ex)
    {
        E_LOG(ex);
        status = -1;
    }

    catch (const std::exception& ex)
    {
        E_LOG(ex.what());
        status = -1;
    }
    catch (const char * ex)
    {
        E_LOG(ex);
        status = -1;
    }

    catch (...)
    {
        E_LOG("Unknown Error");
        status = -1;
    }

    return status;
}

int main(int argc, char* argv[])
{
    MoccaIfTester app;
    return app.start(argc, argv);
}
