#pragma once
#include <saas/util/optional_allocator.h>
#include <kernel/externalrelev/sent_zones.h>
#include <util/system/defaults.h>
#include <util/stream/input.h>
#include <util/stream/output.h>
#include <util/generic/string.h>
#include <util/generic/ylimits.h>
#include <util/generic/vector.h>

namespace NZonesMakeup {

    typedef TSentenceZones TZoneId;
    typedef TSentenceZones TZoneMask;
    typedef ui16 TZoneNumber;
    typedef TVector<TZoneId, TOptionalAllocator> TSentsMakeup;
    typedef TVector<ui32, TOptionalAllocator> TSpansZones;
    typedef TVector<ui16, TOptionalAllocator> TLengthZones;

    struct TZoneCode {
        TZoneId ZoneId;
        TZoneNumber ZoneNumber;
        inline TZoneCode()
            : ZoneId(Max<TZoneId>())
            , ZoneNumber(Max<TZoneNumber>())
        {}

        TZoneCode(TZoneId zoneId, TZoneNumber zoneNumber)
            : ZoneId(zoneId)
            , ZoneNumber(zoneNumber)
        {}
    };

    enum class EZoneRole {
        Title = 1
    };

    class IZonesDescription {
    public:
        virtual ~IZonesDescription() {}
        virtual TZoneCode Decode(const TString& name) = 0;
        virtual NZonesMakeup::TZoneCode AddZone(const TString& name) = 0;
        virtual NZonesMakeup::TZoneCode AddZoneUnsafe(const TString& name) = 0;
        virtual TZoneId GetZoneId(TZoneNumber zoneNumber) const = 0;
        virtual const TString& GetZoneName(TZoneNumber zoneNumber) const = 0;
        virtual TZoneNumber GetZoneCount() const = 0;
        virtual TZoneMask GetZonesMask(EZoneRole role) const = 0;
        virtual void DecodeSpans(TSpansZones& spansZones, const NZonesMakeup::IZonesDescription& currentDescription, bool unsafe = false) = 0;
        virtual TLengthZones DecodeLengths(const NZonesMakeup::TLengthZones& lengthZones, const NZonesMakeup::IZonesDescription& currentDescription, bool unsafe = false) = 0;
        virtual void Serialize(IOutputStream& out) = 0;
        virtual bool Deserialize(IInputStream& in) = 0;
    };
}
