#include "vn_asynch_result_internal.h"

class VN_Asynch_Event_Handler : public ACE_Event_Handler
{

    virtual int handle_timeout(const ACE_Time_Value &current_time, const void *act)
    {
        vn_asynch_result_t *ar = (vn_asynch_result_t *)act;

        ar->future_ptr->detach(ar->observer_ptr.get());

        ar->future_ptr->clear();
            
        delete ar;

        return -1;
    }

    virtual int handle_close (ACE_HANDLE handle, ACE_Reactor_Mask close_mask)
    {
        delete this;

        return -1;
    }
};

vn_asynch_result_t *vn_asynch_result_create()
{
    vn_asynch_result_t *ar = new vn_asynch_result_t;
    ar->future_ptr = VN_Asynch_Result_Ptr(new VN_Asynch_Result(ar));

    return ar;
}

void vn_asynch_result_destroy(vn_asynch_result_t *ar)
{
    ACE_Reactor::instance()->schedule_timer(new VN_Asynch_Event_Handler, ar, ACE_Time_Value(0));
}

int vn_asynch_result_is_ready(vn_asynch_result_t *ar)
{
    return ar->future_ptr->ready();
}

void vn_asynch_result_set_callback(vn_asynch_result_t *ar, vn_asynch_result_callback_t callback, void *user_data)
{
    ar->observer_ptr = VN_Asynch_Result_Observer_Ptr(new VN_Asynch_Result_Observer(callback, user_data));
    ar->future_ptr->attach(ar->observer_ptr.get());
}

vn_result_t *vn_asynch_result_get(vn_asynch_result_t *ar, int timeout_ms)
{
    ACE_Time_Value to = ACE_OS::gettimeofday() + ACE_Time_Value(timeout_ms/1000, (timeout_ms % 1000) * 1000);

    vn_asynch_result_t *dummy;
    
    if (ar->future_ptr->get(dummy, &to) == -1)
    {
        return 0;
    }
    else
    {
        return ar->r;
    }
}

