/*
 * 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_bits.hpp"
#include "proton/internal/data.hpp"
#include "proton/value.hpp"
#include "proton/types.hpp"
#include "proton/scalar.hpp"
#include "proton/error.hpp"

#include <ostream>
#include <sstream>

namespace proton {

using codec::decoder;
using codec::encoder;
using codec::start;

value::value() = default;
value::value(pn_data_t *d) { data_ = make_wrapper(d); }
value::value(const value& x) { *this = x; }
value::value(value&& x) { swap(*this, x); }
value& value::operator=(value&& x) { swap(*this, x); return *this; }

value& value::operator=(const value& x) {
    if (this != &x) {
        if (x.empty())
            clear();
        else
            data().copy(x.data_);
    }
    return *this;
}

void swap(value& x, value& y) { std::swap(x.data_, y.data_); }

void value::clear() { if (!!data_) data_.clear(); }

namespace internal {

// On demand
internal::data& value_base::data() {
    if (!data_)
        data_ = internal::data::create();
    return data_;
}

}

type_id value::type() const {
    return (!data_ || data_.empty()) ? NULL_TYPE : codec::decoder(*this).next_type();
}

bool value::empty() const { return type() == NULL_TYPE; }

namespace {

// Compare nodes, return -1 if a<b, 0 if a==b, +1 if a>b
// Forward-declare so we can use it recursively.
int compare_next(decoder& a, decoder& b);

template <class T> int compare(const T& a, const T& b) {
    if (a < b) return -1;
    else if (a > b) return +1;
    else return 0;
}

int compare_container(decoder& a, decoder& b) {
    start sa, sb;
    a >> sa;
    b >> sb;
    // Compare described vs. not-described.
    int cmp = compare(sa.is_described, sb.is_described);
    if (cmp) return cmp;
    // Lexical sort (including descriptor if there is one)
    size_t min_size = std::min(sa.size, sb.size) + size_t(sa.is_described);
    for (size_t i = 0; i < min_size; ++i) {
        cmp = compare_next(a, b);
        if (cmp) return cmp;
    }
    return compare(sa.size, sb.size);
}

template <class T> int compare_simple(decoder& a, decoder& b) {
    T va = T();
    T vb = T();
    a >> va;
    b >> vb;
    return compare(va, vb);
}

int compare_next(decoder& a, decoder& b) {
    // Sort by type_id first.
    type_id ta = a.next_type(), tb = b.next_type();
    int cmp = compare(ta, tb);
    if (cmp) return cmp;

    switch (ta) {
      case NULL_TYPE: return 0;
      case ARRAY:
      case LIST:
      case MAP:
      case DESCRIBED:
        return compare_container(a, b);
      case BOOLEAN: return compare_simple<bool>(a, b);
      case UBYTE: return compare_simple<uint8_t>(a, b);
      case BYTE: return compare_simple<int8_t>(a, b);
      case USHORT: return compare_simple<uint16_t>(a, b);
      case SHORT: return compare_simple<int16_t>(a, b);
      case UINT: return compare_simple<uint32_t>(a, b);
      case INT: return compare_simple<int32_t>(a, b);
      case ULONG: return compare_simple<uint64_t>(a, b);
      case LONG: return compare_simple<int64_t>(a, b);
      case CHAR: return compare_simple<wchar_t>(a, b);
      case TIMESTAMP: return compare_simple<timestamp>(a, b);
      case FLOAT: return compare_simple<float>(a, b);
      case DOUBLE: return compare_simple<double>(a, b);
      case DECIMAL32: return compare_simple<decimal32>(a, b);
      case DECIMAL64: return compare_simple<decimal64>(a, b);
      case DECIMAL128: return compare_simple<decimal128>(a, b);
      case UUID: return compare_simple<uuid>(a, b);
      case BINARY: return compare_simple<binary>(a, b);
      case STRING: return compare_simple<std::string>(a, b);
      case SYMBOL: return compare_simple<symbol>(a, b);
    }
// Avoid unreached diagnostic from clang
#if defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
    // Invalid but equal type_id, treat as equal.
    return 0;
#if defined(__clang__)
#pragma GCC diagnostic pop
#endif
}

int compare(const value& x, const value& y) {
    decoder a(x), b(y);
    internal::state_guard s1(a), s2(b);
    a.rewind();
    b.rewind();
    while (a.more() && b.more()) {
        int cmp = compare_next(a, b);
        if (cmp != 0) return cmp;
    }
    if (b.more()) return -1;
    if (a.more()) return 1;
    return 0;
}

} // namespace

bool operator==(const value& x, const value& y) {
    if (x.empty() && y.empty()) return true;
    if (x.empty() || y.empty()) return false;
    return compare(x, y) == 0;
}

bool operator<(const value& x, const value& y) {
    if (x.empty() && y.empty()) return false;
    if (x.empty()) return true; // empty is < !empty
    return compare(x, y) < 0;
}

std::ostream& operator<<(std::ostream& o, const value& x) {
    if (type_id_is_scalar(x.type()))
        return o << proton::get<scalar>(x); // Print as a scalar
    // Use pn_inspect for complex types.
    proton::decoder d(x);
    return o << d;
}

std::string to_string(const value& x) {
    std::ostringstream os;
    os << std::boolalpha << x;
    return os.str();
}

void value::reset(pn_data_t *d) { data_ = make_wrapper(d); }

} // namespace proton
