#pragma once
#include "coding/reader.hpp"

#include <cstdint>
#include <optional>

class HouseToStreetTable
{
public:
  enum class Version : uint8_t
  {
    V0 = 0,
    V1 = 1,
    V2 = 2,
    Latest = V2
  };

  enum class StreetIdType
  {
    // Table stores the index number of the correct street corresponding
    // to the house in the list of streets generated by ReverseGeocoder.
    Index,
    // Table stores feature id of street corresponding to the house.
    FeatureId,
    // Empty table.
    None
  };

  struct Header
  {
    template <class Sink>
    void Serialize(Sink & sink) const
    {
      WriteToSink(sink, static_cast<uint8_t>(Version::Latest));
      WriteToSink(sink, m_tableOffset);
      WriteToSink(sink, m_tableSize);
    }

    template <class Source>
    void Read(Source & source)
    {
      m_version = static_cast<Version>(ReadPrimitiveFromSource<uint8_t>(source));
      m_tableOffset = ReadPrimitiveFromSource<uint32_t>(source);
      m_tableSize = ReadPrimitiveFromSource<uint32_t>(source);
    }

    Version m_version = Version::Latest;
    // All offsets are relative to the start of the section (offset of header is zero).
    uint32_t m_tableOffset = 0;
    uint32_t m_tableSize = 0;
  };

  virtual ~HouseToStreetTable() = default;

  struct Result
  {
    uint32_t m_streetId;
    StreetIdType m_type;
  };
  virtual std::optional<Result> Get(uint32_t houseId) const = 0;
};
