#ifndef _VN_CLIENT_CURL_H_
#define _VN_CLIENT_CURL_H_

#include "ace/Cleanup.h"
#include "ace/Reactor.h"
#include "ace/TP_Reactor.h"
#include "ace/Thread_Manager.h"

#include "curl/multi.h"

#include "vn_resource_pool.hpp"
#include "vn_asynch_result_internal.h"
#include "vn_client.h"

template <>
class ACE_Export VN_Resource_Create<CURL>
{
  public:
   CURL *operator () () const //throw (resource_error)
   { 
       CURL *curl = curl_easy_init();
       return curl;

   };
};

template <>
class ACE_Export VN_Resource_Destroy<CURL>
{
  public:
   void operator () (CURL *curl) const 
   { 
       curl_easy_cleanup(curl);
   };
};

class VN_CURL_Result_Handler
{
public:
    
    virtual ~VN_CURL_Result_Handler()
    {
    }

    void handle_result(CURLcode result)
    {
        vn_result_t *vn_result = vn_result_create(result, curl_easy_strerror(result));

        if (result == 0)
            parse(vn_result);

        asynch_result_ptr_->set(vn_result);
    }

    std::string *data()
    {
        return &data_;
    }

protected:
    virtual void parse(vn_result_t *vn_result) = 0;

protected:
    VN_CURL_Result_Handler(const VN_Asynch_Result_Ptr &a)
        : asynch_result_ptr_(a)
    {
    }

protected:
    VN_Asynch_Result_Ptr asynch_result_ptr_;
    std::string data_;
    
};

class VN_CURL_Event_Handler : public ACE_Event_Handler
{
public:
    VN_CURL_Event_Handler();

    virtual ~VN_CURL_Event_Handler();

    void perform(const VN_Resource<CURL> &curl);


public: // redefined virtual methods from ACE_Event_Handler

    virtual int handle_timeout(const ACE_Time_Value &current_time, const void *act);

    virtual int handle_output(ACE_HANDLE fd);
 
    virtual int handle_exception(ACE_HANDLE fd);

    virtual int handle_input(ACE_HANDLE fd);

private:

    int handle_curl_multi(ACE_HANDLE fd);


private:
    CURLM *cm_;
    ACE_Recursive_Thread_Mutex lock_;
    fd_set rfds_, wfds_, efds_;  
};





#endif /* _VN_CLIENT_CURL_H_ */
