/*
 *
 * 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 "proton/codec/map.hpp"
#include "proton/receiver_options.hpp"
#include "proton/messaging_handler.hpp"
#include "proton/source_options.hpp"
#include "proton/target_options.hpp"

#include <proton/link.h>

#include "contexts.hpp"
#include "proactor_container_impl.hpp"
#include "messaging_adapter.hpp"
#include "proton_bits.hpp"

namespace proton {

template <class T> struct option {
    T value;
    bool set;

    option() : value(), set(false) {}
    option& operator=(const T& x) { value = x;  set = true; return *this; }
    void update(const option<T>& x) { if (x.set) *this = x.value; }
};

class receiver_options::impl {
    static link_context& get_context(receiver l) {
        return link_context::get(unwrap(l));
    }

    static void set_delivery_mode(receiver l, proton::delivery_mode mode) {
        switch (mode) {
        case delivery_mode::AT_MOST_ONCE:
            pn_link_set_snd_settle_mode(unwrap(l), PN_SND_SETTLED);
            break;
        case delivery_mode::AT_LEAST_ONCE:
            pn_link_set_snd_settle_mode(unwrap(l), PN_SND_UNSETTLED);
            pn_link_set_rcv_settle_mode(unwrap(l), PN_RCV_FIRST);
            break;
        default:
            break;
        }
    }

  public:
    option<messaging_handler*> handler;
    option<proton::delivery_mode> delivery_mode;
    option<bool> auto_accept;
    option<bool> auto_settle;
    option<int> credit_window;
    option<bool> dynamic_address;
    option<source_options> source;
    option<target_options> target;
    option<std::string> name;
    option<std::map<symbol, value> > properties;


    void apply(receiver& r) {
        if (r.uninitialized()) {
            if (delivery_mode.set) set_delivery_mode(r, delivery_mode.value);
            if (handler.set && handler.value) container::impl::set_handler(r, handler.value);
            if (auto_settle.set) get_context(r).auto_settle = auto_settle.value;
            if (auto_accept.set) get_context(r).auto_accept = auto_accept.value;
            if (credit_window.set) get_context(r).credit_window = credit_window.value;

            if (source.set) {
                proton::source local_s(make_wrapper<proton::source>(pn_link_source(unwrap(r))));
                source.value.apply(local_s);
            }
            if (target.set) {
                proton::target local_t(make_wrapper<proton::target>(pn_link_target(unwrap(r))));
                target.value.apply(local_t);
            }
            if (properties.set) {
                value(pn_link_properties(unwrap(r))) = properties.value;
            }
        }
    }

    void update(const impl& x) {
        handler.update(x.handler);
        delivery_mode.update(x.delivery_mode);
        auto_accept.update(x.auto_accept);
        auto_settle.update(x.auto_settle);
        credit_window.update(x.credit_window);
        dynamic_address.update(x.dynamic_address);
        source.update(x.source);
        target.update(x.target);
        name.update(x.name);
        properties.update(x.properties);
    }

};

receiver_options::receiver_options() : impl_(new impl()) {}
receiver_options::receiver_options(const receiver_options& x) : impl_(new impl()) {
    *this = x;
}
receiver_options::~receiver_options() = default;

receiver_options& receiver_options::operator=(const receiver_options& x) {
    *impl_ = *x.impl_;
    return *this;
}

void receiver_options::update(const receiver_options& x) { impl_->update(*x.impl_); }

receiver_options& receiver_options::handler(class messaging_handler &h) { impl_->handler = &h; return *this; }
receiver_options& receiver_options::delivery_mode(proton::delivery_mode m) {impl_->delivery_mode = m; return *this; }
receiver_options& receiver_options::auto_accept(bool b) {impl_->auto_accept = b; return *this; }
receiver_options& receiver_options::credit_window(int w) {impl_->credit_window = w; return *this; }
receiver_options& receiver_options::source(source_options &s) {impl_->source = s; return *this; }
receiver_options& receiver_options::target(target_options &s) {impl_->target = s; return *this; }
receiver_options& receiver_options::name(const std::string &s) {impl_->name = s; return *this; }
receiver_options& receiver_options::properties(const std::map<symbol, value> &props) { impl_->properties = props; return *this; }

void receiver_options::apply(receiver& r) const { impl_->apply(r); }

const std::string* receiver_options::get_name() const {
    return impl_->name.set ? &impl_->name.value : 0;
}

// No-op, kept for binary compat but auto_settle is not relevant to receiver only sender.
receiver_options& receiver_options::auto_settle(bool b) { return *this; }

} // namespace proton
