#include "preserves.hpp"

#include <fstream>
#include <sstream>

#include "googletest/gtest/gtest.h"

using namespace std;
using namespace Preserves;

TEST(Value, Basics) {
    auto vs = Value<>::from(vector<Value<>>{
        Value<>::from(1),
        Value<>::from(2.0),
        Value<>::from("three"),
    });
    ASSERT_EQ(3U, vs.size());
    ASSERT_EQ(1U, vs[0].to_unsigned());
    ASSERT_EQ(1.0, vs[0].to_double());
    ASSERT_EQ(2.0, vs[1].to_double());
    ASSERT_EQ("three", vs[2].to_string());
    ASSERT_EQ(ValueKind::Sequence, vs.value_kind());
    ASSERT_EQ(ValueKind::String, vs[2].value_kind());
}

TEST(BinaryReader, Negative257) {
    istringstream input("\xA1\xFE\xFF");
    auto v = BinaryReader<>(input).next();
    ASSERT_TRUE(v);
    ASSERT_EQ(v->to_signed(), -257);
}

TEST(BinaryReader, Negative127) {
    istringstream input("\xA0\x81");
    auto v = BinaryReader<>(input).next();
    ASSERT_TRUE(v);
    ASSERT_EQ(v->to_signed(), -127);
}

TEST(BinaryWriter, Negative257) {
    ostringstream s;
    BinaryWriter w(s);
    w << -257;
    std::string output(s.str());
    ASSERT_EQ(output[0], char(BinaryTag::MediumInteger_lo) + 1);
    ASSERT_EQ(output[1], char(0xFE));
    ASSERT_EQ(output[2], char(0xFF));
}

TEST(BinaryWriter, Negative127) {
    ostringstream s;
    BinaryWriter w(s);
    w << -127;
    std::string output(s.str());
    ASSERT_EQ(output[0], char(BinaryTag::MediumInteger_lo));
    ASSERT_EQ(output[1], char(0x81));
}

TEST(BinaryReader, ReadSamples) {
    ifstream f("../../tests/samples.bin", ios::binary);
    BinaryReader<> r(f, &GenericEmbedded::wrap);
    auto v = r.next();
    ASSERT_TRUE(v);
    // BinaryWriter(cerr) << *v;
}