/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */

#include "contexts.hpp"
#include "msg.hpp"
#include "reactor.hpp"
#include "proton_bits.hpp"

#include "proton/error.hpp"

#include <proton/connection.h>
#include <proton/object.h>
#include <proton/link.h>
#include <proton/message.h>
#include <proton/reactor.h>
#include <proton/session.h>

#include <typeinfo>

namespace proton {

namespace {
void cpp_context_finalize(void* v) { reinterpret_cast<context*>(v)->~context(); }
#define CID_cpp_context CID_pn_object
#define cpp_context_initialize NULL
#define cpp_context_finalize cpp_context_finalize
#define cpp_context_hashcode NULL
#define cpp_context_compare NULL
#define cpp_context_inspect NULL
pn_class_t cpp_context_class = PN_CLASS(cpp_context);

// Handles
PN_HANDLE(CONNECTION_CONTEXT)
PN_HANDLE(CONTAINER_CONTEXT)
PN_HANDLE(LISTENER_CONTEXT)
PN_HANDLE(LINK_CONTEXT)

void set_context(pn_record_t* record, pn_handle_t handle, const pn_class_t *clazz, void* value)
{
    pn_record_def(record, handle, clazz);
    pn_record_set(record, handle, value);
}

template <class T>
T* get_context(pn_record_t* record, pn_handle_t handle) {
    return reinterpret_cast<T*>(pn_record_get(record, handle));
}

}

context::~context() {}

void *context::alloc(size_t n) { return pn_object_new(&cpp_context_class, n); }

pn_class_t* context::pn_class() { return &cpp_context_class; }


context::id connection_context::id(pn_connection_t* c) {
    return context::id(pn_connection_attachments(c), CONNECTION_CONTEXT);
}

context::id connection_context::id(const connection& c) {
    return id(unwrap(c));
}

void container_context::set(const reactor& r, container& c) {
    set_context(pn_reactor_attachments(r.pn_object()), CONTAINER_CONTEXT, PN_VOID, &c);
}

container &container_context::get(pn_reactor_t *pn_reactor) {
    container *ctx = get_context<container>(pn_reactor_attachments(pn_reactor), CONTAINER_CONTEXT);
    if (!ctx) throw error(MSG("Reactor has no C++ container context"));
    return *ctx;
}

listener_context& listener_context::get(pn_acceptor_t* a) {
    // TODO aconway 2016-05-13: reactor only
    // A Proton C pn_acceptor_t is really just a selectable
    pn_selectable_t *sel = reinterpret_cast<pn_selectable_t*>(a);

    listener_context* ctx =
        get_context<listener_context>(pn_selectable_attachments(sel), LISTENER_CONTEXT);
    if (!ctx) {
        ctx =  context::create<listener_context>();
        set_context(pn_selectable_attachments(sel), LISTENER_CONTEXT, context::pn_class(), ctx);
        pn_decref(ctx);
    }
    return *ctx;
}

link_context& link_context::get(pn_link_t* l) {
    link_context* ctx =
        get_context<link_context>(pn_link_attachments(l), LINK_CONTEXT);
    if (!ctx) {
        ctx =  context::create<link_context>();
        set_context(pn_link_attachments(l), LINK_CONTEXT, context::pn_class(), ctx);
        pn_decref(ctx);
    }
    return *ctx;
}

}
