#ifndef PROTON_CODEC_DECODER_HPP
#define PROTON_CODEC_DECODER_HPP

/*
 *
 * 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 "../internal/data.hpp"
#include "../internal/type_traits.hpp"
#include "../types_fwd.hpp"
#include "./common.hpp"

#include <proton/type_compat.h>

#include <utility>

/// @file
/// @copybrief proton::codec::decoder

namespace proton {

class annotation_key;
class message_id;
class scalar;
class value;

namespace internal {
class value_base;
}

namespace codec {

/// **Unsettled API** - A stream-like decoder from AMQP bytes to C++
/// values.
///
/// For internal use only.
///
/// @see @ref types_page for the recommended ways to manage AMQP data
class decoder : public internal::data {
  public:
    /// Wrap a Proton C data object.  The exact flag if set means
    /// decode only when there is an exact match between the AMQP and
    /// C++ type. If not set then perform automatic conversions.
    explicit decoder(const data& d, bool exact=false) : data(d), exact_(exact) {}

    /// Attach decoder to a proton::value. The decoder is rewound to
    /// the start of the data.
    PN_CPP_EXTERN explicit decoder(const internal::value_base&, bool exact=false);

    /// Decode AMQP data from a buffer and add it to the end of the
    /// decoders stream.
    PN_CPP_EXTERN void decode(const char* buffer, size_t size);

    /// Decode AMQP data from a std::string and add it to the end of
    /// the decoders stream.
    PN_CPP_EXTERN void decode(const std::string&);

    /// Return true if there are more value to extract at the current level.
    PN_CPP_EXTERN bool more();

    /// Get the type of the next value that will be read by
    /// operator>>.
    ///
    /// @throw conversion_error if no more values. @see
    /// decoder::more().
    PN_CPP_EXTERN type_id next_type();

    /// @name Extract built-in types
    ///
    /// @throw conversion_error if the decoder is empty or has an
    /// incompatible type.
    ///
    /// @{
    PN_CPP_EXTERN decoder& operator>>(bool&);
    PN_CPP_EXTERN decoder& operator>>(uint8_t&);
    PN_CPP_EXTERN decoder& operator>>(int8_t&);
    PN_CPP_EXTERN decoder& operator>>(uint16_t&);
    PN_CPP_EXTERN decoder& operator>>(int16_t&);
    PN_CPP_EXTERN decoder& operator>>(uint32_t&);
    PN_CPP_EXTERN decoder& operator>>(int32_t&);
    PN_CPP_EXTERN decoder& operator>>(wchar_t&);
    PN_CPP_EXTERN decoder& operator>>(uint64_t&);
    PN_CPP_EXTERN decoder& operator>>(int64_t&);
    PN_CPP_EXTERN decoder& operator>>(timestamp&);
    PN_CPP_EXTERN decoder& operator>>(float&);
    PN_CPP_EXTERN decoder& operator>>(double&);
    PN_CPP_EXTERN decoder& operator>>(decimal32&);
    PN_CPP_EXTERN decoder& operator>>(decimal64&);
    PN_CPP_EXTERN decoder& operator>>(decimal128&);
    PN_CPP_EXTERN decoder& operator>>(uuid&);
    PN_CPP_EXTERN decoder& operator>>(std::string&);
    PN_CPP_EXTERN decoder& operator>>(symbol&);
    PN_CPP_EXTERN decoder& operator>>(binary&);
    PN_CPP_EXTERN decoder& operator>>(message_id&);
    PN_CPP_EXTERN decoder& operator>>(annotation_key&);
    PN_CPP_EXTERN decoder& operator>>(scalar&);
    PN_CPP_EXTERN decoder& operator>>(internal::value_base&);
    PN_CPP_EXTERN decoder& operator>>(null&);
#if PN_CPP_HAS_NULLPTR
    PN_CPP_EXTERN decoder& operator>>(decltype(nullptr)&);
#endif
    ///@}

    /// Start decoding a container type, such as an ARRAY, LIST or
    /// MAP.  This "enters" the container, more() will return false at
    /// the end of the container.  Call finish() to "exit" the
    /// container and move on to the next value.
    PN_CPP_EXTERN decoder& operator>>(start&);

    /// Finish decoding a container type, and move on to the next
    /// value in the stream.
    PN_CPP_EXTERN decoder& operator>>(const finish&);

    /// @cond INTERNAL
    template <class T> struct sequence_ref { T& ref; sequence_ref(T& r) : ref(r) {} };
    template <class T> struct associative_ref { T& ref; associative_ref(T& r) : ref(r) {} };
    template <class T> struct pair_sequence_ref { T& ref;  pair_sequence_ref(T& r) : ref(r) {} };

    template <class T> static sequence_ref<T> sequence(T& x) { return sequence_ref<T>(x); }
    template <class T> static associative_ref<T> associative(T& x) { return associative_ref<T>(x); }
    template <class T> static pair_sequence_ref<T> pair_sequence(T& x) { return pair_sequence_ref<T>(x); }
    /// @endcond

    /// Extract any AMQP sequence (ARRAY, LIST or MAP) to a C++
    /// sequence container of T if the elements types are convertible
    /// to T. A MAP is extracted as `[key1, value1, key2, value2...]`.
    template <class T> decoder& operator>>(sequence_ref<T> r)  {
        start s;
        *this >> s;
        if (s.is_described) next();
        r.ref.resize(s.size);
        for (typename T::iterator i = r.ref.begin(); i != r.ref.end(); ++i)
            *this >> *i;
        return *this;
    }

    /// Extract an AMQP MAP to a C++ associative container
    template <class T> decoder& operator>>(associative_ref<T> r)  {
        using namespace internal;
        start s;
        *this >> s;
        assert_type_equal(MAP, s.type);
        r.ref.clear();
        for (size_t i = 0; i < s.size/2; ++i) {
            typename remove_const<typename T::key_type>::type k;
            typename remove_const<typename T::mapped_type>::type v;
            *this >> k >> v;
            r.ref[k] = v;
        }
        return *this;
    }

    /// Extract an AMQP MAP to a C++ push_back sequence of pairs
    /// preserving encoded order.
    template <class T> decoder& operator>>(pair_sequence_ref<T> r)  {
        using namespace internal;
        start s;
        *this >> s;
        assert_type_equal(MAP, s.type);
        r.ref.clear();
        for (size_t i = 0; i < s.size/2; ++i) {
            typedef typename T::value_type value_type;
            typename remove_const<typename value_type::first_type>::type k;
            typename remove_const<typename value_type::second_type>::type v;
            *this >> k >> v;
            r.ref.push_back(value_type(k, v));
        }
        return *this;
    }

  private:
    type_id pre_get();
    template <class T, class U> decoder& extract(T& x, U (*get)(pn_data_t*));
    bool exact_;

  friend class message;
};

/// @cond INTERNAL
/// XXX Document this
template<class T> T get(decoder& d) {
    assert_type_equal(internal::type_id_of<T>::value, d.next_type());
    T x;
    d >> x;
    return x;
}
/// @endcond

/// operator>> for integer types that are not covered by the standard
/// overrides.
template <class T> typename internal::enable_if<internal::is_unknown_integer<T>::value, decoder&>::type
operator>>(decoder& d, T& i)  {
    using namespace internal;
    typename integer_type<sizeof(T), is_signed<T>::value>::type v;
    d >> v;                     // Extract as a known integer type
    i = v;                      // C++ conversion to the target type.
    return d;
}

} // codec
} // proton

#endif // PROTON_CODEC_DECODER_HPP
