#!/bin/sh
set -e

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

cat > "$TMPDIR/test_roundtrip.cpp" << 'EOF'
#include <vtzero/vector_tile.hpp>
#include <vtzero/builder.hpp>
#include <vtzero/index.hpp>
#include <cassert>
#include <iostream>
#include <string>
#include <unordered_map>

int main() {
    std::cout << "Testing multi-layer tile roundtrip\n";

    vtzero::tile_builder tile;
    vtzero::layer_builder lyr_roads{tile, "roads", 2, 4096};
    vtzero::layer_builder lyr_pois{tile, "pois"};
    vtzero::layer_builder lyr_water{tile, "water"};

    std::cout << "  Building 'roads' layer (linestrings, extent=4096)\n";
    vtzero::key_index<std::unordered_map> road_keys{lyr_roads};
    {
        vtzero::linestring_feature_builder f{lyr_roads};
        f.set_id(100);
        f.add_linestring(2);
        f.set_point(0, 0);
        f.set_point(4096, 0);
        f.add_property(road_keys("highway"), "primary");
        f.add_property(road_keys("name"), "Main Street");
        f.commit();
    }
    {
        vtzero::linestring_feature_builder f{lyr_roads};
        f.set_id(101);
        f.add_linestring(2);
        f.set_point(0, 2048);
        f.set_point(4096, 2048);
        f.add_property(road_keys("highway"), "secondary");
        f.add_property(road_keys("name"), "Side Street");
        f.commit();
    }

    std::cout << "  Building 'pois' layer (points, no feature IDs)\n";
    {
        vtzero::point_feature_builder f{lyr_pois};
        f.add_point(1000, 1000);
        f.add_property("type", "restaurant");
        f.commit();
    }
    {
        vtzero::point_feature_builder f{lyr_pois};
        f.add_point(2000, 2000);
        f.add_property("type", "cafe");
        f.commit();
    }
    {
        vtzero::point_feature_builder f{lyr_pois};
        f.add_point(3000, 3000);
        f.add_property("type", "park");
        f.commit();
    }

    std::cout << "  Building 'water' layer (polygon)\n";
    {
        vtzero::polygon_feature_builder f{lyr_water};
        f.set_id(200);
        f.add_ring(5);
        f.set_point(500, 500);
        f.set_point(1500, 500);
        f.set_point(1500, 1500);
        f.set_point(500, 1500);
        f.set_point(500, 500);
        f.add_property("natural", "water");
        f.commit();
    }

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

    vtzero::vector_tile vt{data};
    assert(vt.count_layers() == 3);
    std::cout << "  Layer count: 3 OK\n";

    {
        auto layer = vt.next_layer();
        assert(layer);
        assert(std::string(layer.name()) == "roads");
        assert(layer.version() == 2);
        assert(layer.extent() == 4096);
        assert(layer.num_features() == 2);
        assert(layer.key_table().size() == 2);
        std::cout << "  'roads': version=" << layer.version()
                  << " extent=" << layer.extent()
                  << " features=" << layer.num_features()
                  << " keys=" << layer.key_table().size() << " OK\n";

        auto f1 = layer.next_feature();
        assert(f1 && f1.has_id() && f1.id() == 100);
        assert(f1.geometry_type() == vtzero::GeomType::LINESTRING);
        auto p1 = f1.next_property();
        assert(p1 && std::string(p1.key()) == "highway");
        assert(std::string(p1.value().string_value()) == "primary");
        auto p2 = f1.next_property();
        assert(p2 && std::string(p2.key()) == "name");
        assert(std::string(p2.value().string_value()) == "Main Street");
        std::cout << "    Feature id=100: highway=primary name=Main Street OK\n";

        auto f2 = layer.next_feature();
        assert(f2 && f2.has_id() && f2.id() == 101);
        auto p3 = f2.next_property();
        assert(p3 && std::string(p3.key()) == "highway");
        assert(std::string(p3.value().string_value()) == "secondary");
        auto p4 = f2.next_property();
        assert(p4 && std::string(p4.key()) == "name");
        assert(std::string(p4.value().string_value()) == "Side Street");
        std::cout << "    Feature id=101: highway=secondary name=Side Street OK\n";
    }

    {
        auto layer = vt.next_layer();
        assert(layer);
        assert(std::string(layer.name()) == "pois");
        assert(layer.num_features() == 3);
        std::cout << "  'pois': features=" << layer.num_features() << " OK\n";

        auto f = layer.next_feature();
        assert(f && !f.has_id());
        assert(f.geometry_type() == vtzero::GeomType::POINT);
        auto p = f.next_property();
        assert(p && std::string(p.key()) == "type");
        assert(std::string(p.value().string_value()) == "restaurant");
        std::cout << "    Feature (no id): type=restaurant OK\n";

        f = layer.next_feature();
        assert(f && !f.has_id());
        p = f.next_property();
        assert(std::string(p.value().string_value()) == "cafe");
        std::cout << "    Feature (no id): type=cafe OK\n";

        f = layer.next_feature();
        assert(f && !f.has_id());
        p = f.next_property();
        assert(std::string(p.value().string_value()) == "park");
        std::cout << "    Feature (no id): type=park OK\n";
    }

    {
        auto layer = vt.next_layer();
        assert(layer);
        assert(std::string(layer.name()) == "water");
        assert(layer.num_features() == 1);
        std::cout << "  'water': features=" << layer.num_features() << " OK\n";

        auto f = layer.next_feature();
        assert(f && f.has_id() && f.id() == 200);
        assert(f.geometry_type() == vtzero::GeomType::POLYGON);
        auto p = f.next_property();
        assert(p && std::string(p.key()) == "natural");
        assert(std::string(p.value().string_value()) == "water");
        std::cout << "    Feature id=200: natural=water type="
                  << vtzero::geom_type_name(f.geometry_type()) << " OK\n";
    }

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

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