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

#include "proton/annotation_key.hpp"
#include "proton/binary.hpp"
#include "proton/decimal.hpp"
#include "proton/message_id.hpp"
#include "proton/scalar.hpp"
#include "proton/symbol.hpp"
#include "proton/timestamp.hpp"
#include "proton/value.hpp"

#include "proton_bits.hpp"
#include "types_internal.hpp"
#include "msg.hpp"

#include <proton/codec.h>

namespace proton {
namespace codec {

/**@file
 *
 * Note the pn_data_t "current" node is always pointing *before* the next value
 * to be returned by the decoder.
 */
decoder::decoder(const internal::value_base& v, bool exact)
    : data(const_cast<internal::value_base&>(v).data()), exact_(exact)
{
    rewind();
}

namespace {
template <class T> T check(T result) {
    if (result < 0)
        throw conversion_error(error_str(result));
    return result;
}
}

void decoder::decode(const char* i, size_t size) {
    internal::state_guard sg(*this);
    const char* end = i + size;
    while (i < end)
        i += check(pn_data_decode(pn_object(), i, size_t(end - i)));
}

void decoder::decode(const std::string& s) { decode(s.data(), s.size()); }

bool decoder::more() {
    internal::state_guard sg(*this);
    return next();
}

type_id decoder::pre_get() {
    if (!next()) throw conversion_error("no more data");
    type_id t = type_id(pn_data_type(pn_object()));
    if (t < 0) throw conversion_error("invalid data");
    return t;
}

namespace {

template <class T, class U> void assign(T& x, const U& y) { x = y; }
void assign(uuid& x, const pn_uuid_t y) { byte_copy(x, y); }
void assign(decimal32& x, const pn_decimal32_t y) { byte_copy(x, y); }
void assign(decimal64& x, const pn_decimal64_t y)  { byte_copy(x, y); }
void assign(decimal128& x, const pn_decimal128_t y) { byte_copy(x, y); }
void assign(symbol& x, const pn_bytes_t y) { x = str(y); }
void assign(binary& x, const pn_bytes_t y) { x = bin(y); }

} // namespace


// Simple extract with no type conversion.
template <class T, class U> decoder& decoder::extract(T& x, U (*get)(pn_data_t*)) {
    internal::state_guard sg(*this);
    assert_type_equal(internal::type_id_of<T>::value, pre_get());
    assign(x, get(pn_object()));
    sg.cancel();                // No error, cancel the reset.
    return *this;
}

type_id decoder::next_type() {
    internal::state_guard sg(*this);
    return pre_get();
}

decoder& decoder::operator>>(start& s) {
    internal::state_guard sg(*this);
    s.type = pre_get();
    switch (s.type) {
      case ARRAY:
        s.size = pn_data_get_array(pn_object());
        s.element = type_id(pn_data_get_array_type(pn_object())); s.is_described = pn_data_is_array_described(pn_object());
        break;
      case LIST:
        s.size = pn_data_get_list(pn_object());
        break;
      case MAP:
        s.size = pn_data_get_map(pn_object());
        break;
      case DESCRIBED:
        s.is_described = true;
        s.size = 1;
        break;
      default:
        throw conversion_error(MSG("" << s.type << " is not a container type"));
    }
    pn_data_enter(pn_object());
    sg.cancel();
    return *this;
}

decoder& decoder::operator>>(const finish&) {
    pn_data_exit(pn_object());
    return *this;
}

decoder& decoder::operator>>(null&) {
    internal::state_guard sg(*this);
    assert_type_equal(NULL_TYPE, pre_get());
    return *this;
}

decoder& decoder::operator>>(decltype(nullptr)&) {
    internal::state_guard sg(*this);
    assert_type_equal(NULL_TYPE, pre_get());
    return *this;
}

decoder& decoder::operator>>(internal::value_base& x) {
    if (*this == x.data_)
        throw conversion_error("extract into self");
    data d = x.data();
    d.clear();
    narrow();
    try {
        check(d.appendn(*this, 1));
        widen();
    } catch(...) {
        widen();
        throw;
    }
    next();
    return *this;
}

decoder& decoder::operator>>(message_id& x) {
    internal::state_guard sg(*this);
    type_id got = pre_get();
    if (got != ULONG && got != UUID && got != BINARY && got != STRING)
        throw conversion_error(
            msg() << "expected one of ulong, uuid, binary or string but found " << got);
    x.set(pn_data_get_atom(pn_object()));
    sg.cancel();
    return *this;
}

decoder& decoder::operator>>(annotation_key& x) {
    internal::state_guard sg(*this);
    type_id got = pre_get();
    if (got != ULONG && got != SYMBOL)
        throw conversion_error(msg() << "expected one of ulong or symbol but found " << got);
    x.set(pn_data_get_atom(pn_object()));
    sg.cancel();
    return *this;
}

decoder& decoder::operator>>(scalar& x) {
    internal::state_guard sg(*this);
    type_id got = pre_get();
    if (!type_id_is_scalar(got))
        throw conversion_error("expected scalar, found "+type_name(got));
    x.set(pn_data_get_atom(pn_object()));
    sg.cancel();                // No error, no rewind
    return *this;
}

decoder& decoder::operator>>(bool &x) { return extract(x, pn_data_get_bool); }

decoder& decoder::operator>>(uint8_t &x)  { return extract(x, pn_data_get_ubyte); }

decoder& decoder::operator>>(int8_t &x) { return extract(x, pn_data_get_byte); }

decoder& decoder::operator>>(uint16_t &x) {
    internal::state_guard sg(*this);
    type_id tid = pre_get();
    if (exact_) assert_type_equal(USHORT, tid);
    switch (tid) {
      case UBYTE: x = pn_data_get_ubyte(pn_object()); break;
      case USHORT: x = pn_data_get_ushort(pn_object()); break;
      default: assert_type_equal(USHORT, tid);
    }
    sg.cancel();
    return *this;
}

decoder& decoder::operator>>(int16_t &x) {
    internal::state_guard sg(*this);
    type_id tid = pre_get();
    if (exact_) assert_type_equal(SHORT, tid);
    switch (tid) {
      case BYTE: x = pn_data_get_byte(pn_object()); break;
      case SHORT: x = pn_data_get_short(pn_object()); break;
      default: assert_type_equal(SHORT, tid);
    }
    sg.cancel();
    return *this;
}

decoder& decoder::operator>>(uint32_t &x) {
    internal::state_guard sg(*this);
    type_id tid = pre_get();
    if (exact_) assert_type_equal(UINT, tid);
    switch (tid) {
      case UBYTE: x = pn_data_get_ubyte(pn_object()); break;
      case USHORT: x = pn_data_get_ushort(pn_object()); break;
      case UINT: x = pn_data_get_uint(pn_object()); break;
      default: assert_type_equal(UINT, tid);
    }
    sg.cancel();
    return *this;
}

decoder& decoder::operator>>(int32_t &x) {
    internal::state_guard sg(*this);
    type_id tid = pre_get();
    if (exact_) assert_type_equal(INT, tid);
    switch (tid) {
      case BYTE: x = pn_data_get_byte(pn_object()); break;
      case SHORT: x = pn_data_get_short(pn_object()); break;
      case INT: x = pn_data_get_int(pn_object()); break;
      default: assert_type_equal(INT, tid);
    }
    sg.cancel();
    return *this;
}

decoder& decoder::operator>>(uint64_t &x) {
    internal::state_guard sg(*this);
    type_id tid = pre_get();
    if (exact_) assert_type_equal(ULONG, tid);
    switch (tid) {
      case UBYTE: x = pn_data_get_ubyte(pn_object()); break;
      case USHORT: x = pn_data_get_ushort(pn_object()); break;
      case UINT: x = pn_data_get_uint(pn_object()); break;
      case ULONG: x = pn_data_get_ulong(pn_object()); break;
      default: assert_type_equal(ULONG, tid);
    }
    sg.cancel();
    return *this;
}

decoder& decoder::operator>>(int64_t &x) {
    internal::state_guard sg(*this);
    type_id tid = pre_get();
    if (exact_) assert_type_equal(LONG, tid);
    switch (tid) {
      case BYTE: x = pn_data_get_byte(pn_object()); break;
      case SHORT: x = pn_data_get_short(pn_object()); break;
      case INT: x = pn_data_get_int(pn_object()); break;
      case LONG: x = pn_data_get_long(pn_object()); break;
      default: assert_type_equal(LONG, tid);
    }
    sg.cancel();
    return *this;
}

decoder& decoder::operator>>(wchar_t &x) { return extract(x, pn_data_get_char); }

decoder& decoder::operator>>(timestamp &x) { return extract(x, pn_data_get_timestamp); }

decoder& decoder::operator>>(float &x) {
    internal::state_guard sg(*this);
    type_id tid = pre_get();
    if (exact_) assert_type_equal(FLOAT, tid);
    switch (tid) {
      case FLOAT: x = pn_data_get_float(pn_object()); break;
      case DOUBLE: x = float(pn_data_get_double(pn_object())); break;
      default: assert_type_equal(FLOAT, tid);
    }
    sg.cancel();
    return *this;
}

decoder& decoder::operator>>(double &x) {
    internal::state_guard sg(*this);
    type_id tid = pre_get();
    if (exact_) assert_type_equal(DOUBLE, tid);
    switch (tid) {
      case FLOAT: x = static_cast<double>(pn_data_get_float(pn_object())); break;
      case DOUBLE: x = pn_data_get_double(pn_object()); break;
      default: assert_type_equal(DOUBLE, tid);
    }
    sg.cancel();
    return *this;
}

decoder& decoder::operator>>(decimal32 &x) { return extract(x, pn_data_get_decimal32); }
decoder& decoder::operator>>(decimal64 &x) { return extract(x, pn_data_get_decimal64); }
decoder& decoder::operator>>(decimal128 &x)  { return extract(x, pn_data_get_decimal128); }

decoder& decoder::operator>>(uuid &x)  { return extract(x, pn_data_get_uuid); }
decoder& decoder::operator>>(binary &x)  { return extract(x, pn_data_get_binary); }
decoder& decoder::operator>>(symbol &x)  { return extract(x, pn_data_get_symbol); }

decoder& decoder::operator>>(std::string &x)  {
    internal::state_guard sg(*this);
    type_id tid = pre_get();
    if (exact_) assert_type_equal(STRING, tid);
    switch (tid) {
      case STRING: x = str(pn_data_get_string(pn_object())); break;
      case SYMBOL: x = str(pn_data_get_symbol(pn_object())); break;
      default: assert_type_equal(STRING, tid);
    }
    sg.cancel();
    return *this;
}

} // codec
} // proton
