#!/bin/sh
set -e

TMPDIR=$(mktemp -d)
trap 'rm -rf "$TMPDIR"' EXIT

cat > "$TMPDIR/test_properties.cpp" << 'EOF'
#include <vtzero/vector_tile.hpp>
#include <vtzero/builder.hpp>
#include <cassert>
#include <cmath>
#include <cstdint>
#include <iostream>
#include <string>

int main() {
    std::cout << "Testing property value types\n";

    vtzero::tile_builder tile;
    vtzero::layer_builder layer{tile, "test"};

    std::cout << "  Building feature with all 7 property types\n";
    {
        vtzero::point_feature_builder f{layer};
        f.set_id(42);
        f.add_point(0, 0);
        f.add_property("str_key",    "hello vtzero");
        f.add_property("float_key",  vtzero::float_value_type{3.14f});
        f.add_property("double_key", vtzero::double_value_type{2.718281828});
        f.add_property("int_key",    vtzero::int_value_type{-100000});
        f.add_property("uint_key",   vtzero::uint_value_type{200000U});
        f.add_property("sint_key",   vtzero::sint_value_type{-42});
        f.add_property("bool_key",   vtzero::bool_value_type{true});
        f.commit();
    }

    const std::string data = tile.serialize();
    std::cout << "  Tile serialized: " << data.size() << " bytes\n";

    vtzero::vector_tile vt{data};
    auto read_layer = vt.next_layer();
    assert(read_layer);
    assert(read_layer.num_features() == 1);
    assert(read_layer.key_table().size() == 7);
    assert(read_layer.value_table().size() == 7);
    std::cout << "  Layer: 7 keys, 7 values in tables OK\n";

    auto feat = read_layer.next_feature();
    assert(feat);
    assert(feat.has_id() && feat.id() == 42);
    std::cout << "  Feature id=42 OK\n";

    {
        auto p = feat.next_property();
        assert(p);
        assert(std::string(p.key()) == "str_key");
        assert(p.value().type() == vtzero::property_value_type::string_value);
        const std::string val{p.value().string_value()};
        assert(val == "hello vtzero");
        std::cout << "  str_key = \"" << val << "\" ["
                  << vtzero::property_value_type_name(p.value().type()) << "] OK\n";
    }

    {
        auto p = feat.next_property();
        assert(p);
        assert(std::string(p.key()) == "float_key");
        assert(p.value().type() == vtzero::property_value_type::float_value);
        const float val = p.value().float_value();
        assert(std::abs(val - 3.14f) < 0.001f);
        std::cout << "  float_key = " << val << " ["
                  << vtzero::property_value_type_name(p.value().type()) << "] OK\n";
    }

    {
        auto p = feat.next_property();
        assert(p);
        assert(std::string(p.key()) == "double_key");
        assert(p.value().type() == vtzero::property_value_type::double_value);
        const double val = p.value().double_value();
        assert(std::abs(val - 2.718281828) < 1e-9);
        std::cout << "  double_key = " << val << " ["
                  << vtzero::property_value_type_name(p.value().type()) << "] OK\n";
    }

    {
        auto p = feat.next_property();
        assert(p);
        assert(std::string(p.key()) == "int_key");
        assert(p.value().type() == vtzero::property_value_type::int_value);
        const int64_t val = p.value().int_value();
        assert(val == -100000);
        std::cout << "  int_key = " << val << " ["
                  << vtzero::property_value_type_name(p.value().type()) << "] OK\n";
    }

    {
        auto p = feat.next_property();
        assert(p);
        assert(std::string(p.key()) == "uint_key");
        assert(p.value().type() == vtzero::property_value_type::uint_value);
        const uint64_t val = p.value().uint_value();
        assert(val == 200000U);
        std::cout << "  uint_key = " << val << " ["
                  << vtzero::property_value_type_name(p.value().type()) << "] OK\n";
    }

    {
        auto p = feat.next_property();
        assert(p);
        assert(std::string(p.key()) == "sint_key");
        assert(p.value().type() == vtzero::property_value_type::sint_value);
        const int64_t val = p.value().sint_value();
        assert(val == -42);
        std::cout << "  sint_key = " << val << " ["
                  << vtzero::property_value_type_name(p.value().type()) << "] OK\n";
    }

    {
        auto p = feat.next_property();
        assert(p);
        assert(std::string(p.key()) == "bool_key");
        assert(p.value().type() == vtzero::property_value_type::bool_value);
        const bool val = p.value().bool_value();
        assert(val == true);
        std::cout << "  bool_key = " << (val ? "true" : "false") << " ["
                  << vtzero::property_value_type_name(p.value().type()) << "] OK\n";
    }

    assert(!feat.next_property());
    std::cout << "  No more properties (expected) OK\n";

    std::cout << "Property type test PASSED\n";
    return 0;
}
EOF

echo "Compiling property types test..."
g++ -std=c++14 -o "$TMPDIR/test_properties" "$TMPDIR/test_properties.cpp" -I/usr/include
echo "Running property types test..."
"$TMPDIR/test_properties"
