/*
 *
 * 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/map.hpp"

#include "proton/annotation_key.hpp"
#include "proton/scalar.hpp"
#include "proton/value.hpp"
#include "proton/codec/decoder.hpp"
#include "proton/codec/encoder.hpp"
#include "proton/codec/map.hpp"

#include <map>
#include <string>

// IMPLEMENTATION NOTES:
// - if (map_.get()) then *map_ is the authority and value_ is empty()
// - cache() ensures that *map_ is up to date and value_ is cleared.
// - flush() ensures value_ is up to date and map_ is cleared.

namespace proton {

// use std::map as the actual map implementation type
template <class K, class T>
class map_type_impl : public std::map<K, T> {
  // Inherit constructors from std::map for convenience
  using std::map<K,T>::map;

public:
    map_type_impl() = default;
    map_type_impl(const std::map<K, T>& x) : std::map<K, T>(x) {};
};

template <class K, class T>
map<K,T>::map() = default;

template <class K, class T>
map<K,T>::map(const map& x) { *this = x; }

template <class K, class T>
map<K,T>::map(const std::initializer_list<std::pair<const K, T>>& x) : map_(new map_type(x)) {
}

template <class K, class T>
map<K,T>::map(const std::map<K, T>& x) : map_(new map_type(x)) {
}

template <class K, class T>
map<K,T>& map<K,T>::operator=(const std::map<K, T>& x) {
  map_.reset(new map_type(x));
  return *this;
}

template <class K, class T>
map<K,T>::map(pn_data_t *d) : value_(d) {
    // NOTE: for internal use. Don't verify that the data is valid here as that
    // would forcibly decode message maps immediately, we want to decode on-demand.
}

template <class K, class T>
PN_CPP_EXTERN void swap(map<K,T>& x, map<K,T>& y) {
    using namespace std;
    swap(x.map_, y.map_);
    swap(x.value_, y.value_);
}

template <class K, class T>
map<K,T>& map<K,T>::operator=(const map& x) {
    if (&x != this) {
        map_.reset(x.map_.get() ? new map_type(*x.map_) : 0);
        value_ = x.value_;
    }
    return *this;
}

template <class K, class T>
map<K,T>::map(map&& x) :
    map_(std::move(x.map_)), value_(std::move(x.value_)) {}

template <class K, class T>
map<K,T>& map<K,T>::operator=(map&& x) {
    if (&x != this) {
        map_.reset(x.map_.release());
        value_ = std::move(x.value_);
    }
    return *this;
}

template <class K, class T>
map<K,T>::~map() = default;

// Make sure map_ is valid
template <class K, class T>
typename map<K,T>::map_type& map<K,T>::cache() const {
    if (!map_) {
        map_.reset(new map_type);
        if (!value_.empty()) {
            proton::get(value_, *map_);
            value_.clear();
        }
    }
    return *map_;
}

// Make sure value_ is valid
template <class K, class T>
value& map<K,T>::flush() const {
    if (map_.get()) {
        value_ = *map_;
        map_.reset();
    } else if (value_.empty()) {
        // Must contain an empty map, not be an empty value.
        codec::encoder(value_) << codec::start::map() << codec::finish();
    }
    return value_;
}

template <class K, class T>
void map<K,T>::value(const proton::value& x) {
    if (x.empty()) {
        clear();
    } else {
        std::unique_ptr<map_type> tmp(new map_type);
        proton::get(x, *tmp);  // Validate by decoding, may throw
        map_.reset(tmp.release());
        value_.clear();
    }
}

template <class K, class T>
proton::value& map<K,T>::value() { return flush(); }

template <class K, class T>
const proton::value& map<K,T>::value() const { return flush(); }

template <class K, class T>
T map<K,T>::get(const K& k) const {
    if (this->empty()) return T();
    typename map_type::const_iterator i = cache().find(k);
    if (i == map_->end()) return T();
    return i->second;
}

template <class K, class T>
void map<K,T>::put(const K& k, const T& v) {
    cache()[k] = v;
}

template <class K, class T>
size_t map<K,T>::erase(const K& k) {
    if (this->empty()) {
        return 0;
    } else {
        return cache().erase(k);
    }
}

template <class K, class T>
bool map<K,T>::exists(const K& k) const {
    return this->empty() ? 0 : cache().find(k) != cache().end();
}

template <class K, class T>
size_t map<K,T>::size() const {
    return this->empty() ? 0 : cache().size();
}

template <class K, class T>
void map<K,T>::clear() {
    map_.reset();               // Must invalidate the cache on clear()
    value_.clear();
}

template <class K, class T>
bool map<K,T>::empty() const {
    if (map_.get()) {
        return map_->empty();
    }
    if (value_.empty()) {
        return true;
    }
    // We must decode the non-empty value to see if it is an empty map.
    return cache().empty();
}

// Point to a different underlying pn_data_t, no copy
template <class K, class T>
void map<K,T>::reset(pn_data_t *d) {
    value_.reset(d);            // Points to d, not copy of d.
    map_.reset();
    // NOTE: for internal use. Don't verify that the data is valid here as that
    // would forcibly decode message maps immediately, we want to decode on-demand.
}

template <class K, class T>
PN_CPP_EXTERN proton::codec::decoder& operator>>(proton::codec::decoder& d, map<K,T>& m)
{
    m.map_.reset();
    d >> m.value_;
    m.cache();                  // Validate the value
    return d;
}

template <class K, class T>
PN_CPP_EXTERN proton::codec::encoder& operator<<(proton::codec::encoder& e, const map<K,T>& m)
{
    return e << m.value();   // Copy the value
}

// Force the necessary template instantiations so that the library exports the correct symbols
template class PN_CPP_CLASS_EXTERN map<std::string, scalar>;
typedef map<std::string, scalar> cm1;
template PN_CPP_EXTERN void swap<>(cm1&, cm1&);
template PN_CPP_EXTERN proton::codec::decoder& operator>> <>(proton::codec::decoder& d, cm1& m);
template PN_CPP_EXTERN proton::codec::encoder& operator<< <>(proton::codec::encoder& e, const cm1& m);

template class PN_CPP_CLASS_EXTERN map<annotation_key, value>;
typedef map<annotation_key, value> cm2;
template PN_CPP_EXTERN void swap<>(cm2&, cm2&);
template PN_CPP_EXTERN proton::codec::decoder& operator>> <>(proton::codec::decoder& d, cm2& m);
template PN_CPP_EXTERN proton::codec::encoder& operator<< <>(proton::codec::encoder& e, const cm2& m);

template class PN_CPP_CLASS_EXTERN map<symbol, value>;
typedef map<symbol, value> cm3;
template PN_CPP_EXTERN void swap<>(cm3&, cm3&);
template PN_CPP_EXTERN proton::codec::decoder& operator>> <>(proton::codec::decoder& d, cm3& m);
template PN_CPP_EXTERN proton::codec::encoder& operator<< <>(proton::codec::encoder& e, const cm3& m);

} // namespace proton
