/*
 * 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() {}
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
