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

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

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

#include <proton/codec.h>

#include <algorithm>
#include <assert.h>

namespace proton {
namespace codec {

void encoder::check(long result) {
    if (result < 0)
        throw conversion_error(error_str(pn_data_error(pn_object()), result));
}


encoder::encoder(internal::value_base& v) : data(v.data()) {
    clear();
}

bool encoder::encode(char* buffer, size_t& size) {
    internal::state_guard sg(*this); // In case of error
    ssize_t result = pn_data_encode(pn_object(), buffer, size);
    if (result == PN_OVERFLOW) {
        result = pn_data_encoded_size(pn_object());
        if (result >= 0) {
            size = size_t(result);
            return false;
        }
    }
    check(result);
    size = size_t(result);
    sg.cancel();                // Don't restore state, all is well.
    pn_data_clear(pn_object());
    return true;
}

void encoder::encode(std::string& s) {
    s.resize(std::max(s.capacity(), size_t(1))); // Use full capacity, ensure not empty
    size_t size = s.size();
    assert(!s.empty());
    if (!encode(&s[0], size)) {
        s.resize(size);
        assert(!s.empty());
        encode(&s[0], size);
    }
}

std::string encoder::encode() {
    std::string s;
    encode(s);
    return s;
}

encoder& encoder::operator<<(const start& s) {
    switch (s.type) {
      case ARRAY: pn_data_put_array(pn_object(), s.is_described, pn_type_t(s.element)); break;
      case MAP: pn_data_put_map(pn_object()); break;
      case LIST: pn_data_put_list(pn_object()); break;
      case DESCRIBED: pn_data_put_described(pn_object()); break;
      default:
        throw conversion_error(MSG("" << s.type << " is not a container type"));
    }
    pn_data_enter(pn_object());
    return *this;
}

encoder& encoder::operator<<(const finish&) {
    pn_data_exit(pn_object());
    return *this;
}

namespace {

template <class T, class U> T coerce(const U &x) { return x; }
template <> pn_uuid_t coerce(const uuid& x) { pn_uuid_t y; byte_copy(y, x); return  y; }
template <> pn_decimal32_t coerce(const decimal32 &x) { pn_decimal32_t y; byte_copy(y, x); return  y; }
template <> pn_decimal64_t coerce(const decimal64 &x) { pn_decimal64_t y; byte_copy(y, x); return  y; }
template <> pn_decimal128_t coerce(const decimal128 &x) { pn_decimal128_t y; byte_copy(y, x); return  y; }

int pn_data_put_amqp_string(pn_data_t *d, const std::string& x) { return pn_data_put_string(d, pn_bytes(x)); }
int pn_data_put_amqp_binary(pn_data_t *d, const binary& x) { return pn_data_put_binary(d, pn_bytes(x)); }
int pn_data_put_amqp_symbol(pn_data_t *d, const symbol& x) { return pn_data_put_symbol(d, pn_bytes(x)); }
} // namespace

template <class T, class U>
encoder& encoder::insert(const T& x, int (*put)(pn_data_t*, U)) {
    internal::state_guard sg(*this);         // Save state in case of error.
    check(put(pn_object(), coerce<U>(x)));
    sg.cancel();                // Don't restore state, all is good.
    return *this;
}

encoder& encoder::operator<<(bool x) { return insert(x, pn_data_put_bool); }
encoder& encoder::operator<<(uint8_t x) { return insert(x, pn_data_put_ubyte); }
encoder& encoder::operator<<(int8_t x) { return insert(x, pn_data_put_byte); }
encoder& encoder::operator<<(uint16_t x) { return insert(x, pn_data_put_ushort); }
encoder& encoder::operator<<(int16_t x) { return insert(x, pn_data_put_short); }
encoder& encoder::operator<<(uint32_t x) { return insert(x, pn_data_put_uint); }
encoder& encoder::operator<<(int32_t x) { return insert(x, pn_data_put_int); }
encoder& encoder::operator<<(wchar_t x) { return insert(x, pn_data_put_char); }
encoder& encoder::operator<<(uint64_t x) { return insert(x, pn_data_put_ulong); }
encoder& encoder::operator<<(int64_t x) { return insert(x, pn_data_put_long); }
encoder& encoder::operator<<(timestamp x) { return insert(x.milliseconds(), pn_data_put_timestamp); }
encoder& encoder::operator<<(float x) { return insert(x, pn_data_put_float); }
encoder& encoder::operator<<(double x) { return insert(x, pn_data_put_double); }
encoder& encoder::operator<<(decimal32 x) { return insert(x, pn_data_put_decimal32); }
encoder& encoder::operator<<(decimal64 x) { return insert(x, pn_data_put_decimal64); }
encoder& encoder::operator<<(decimal128 x) { return insert(x, pn_data_put_decimal128); }
encoder& encoder::operator<<(const uuid& x) { return insert(x, pn_data_put_uuid); }
encoder& encoder::operator<<(const std::string& x) { return insert(x, pn_data_put_amqp_string); }
encoder& encoder::operator<<(const symbol& x) { return insert(x, pn_data_put_amqp_symbol); }
encoder& encoder::operator<<(const binary& x) { return insert(x, pn_data_put_amqp_binary); }
encoder& encoder::operator<<(const null&) { pn_data_put_null(pn_object()); return *this; }
encoder& encoder::operator<<(decltype(nullptr)) { pn_data_put_null(pn_object()); return *this; }

encoder& encoder::operator<<(const scalar_base& x) { return insert(x.atom_, pn_data_put_atom); }

encoder& encoder::operator<<(const internal::value_base& x) {
    data d = x.data_;
    if (*this == d)
        throw conversion_error("cannot insert into self");
    if (!d || d.empty())
        return *this << null();
    d.rewind();
    check(append(d));
    return *this;
}

} // codec
} // proton
