# KEKS -- Python KEKS implementation
# Copyright (C) 2024-2025 Anton Rudenko <rudenko.ad@phystech.edu>
#               2024-2025 Sergey Matveev <stargrave@stargrave.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this program.  If not, see <http://www.gnu.org/licenses/>.

from hypothesis.strategies import binary
from hypothesis.strategies import booleans
from hypothesis.strategies import characters
from hypothesis.strategies import datetimes
from hypothesis.strategies import deferred
from hypothesis.strategies import dictionaries
from hypothesis.strategies import integers
from hypothesis.strategies import just
from hypothesis.strategies import lists
from hypothesis.strategies import none
from hypothesis.strategies import one_of
from hypothesis.strategies import text
from hypothesis.strategies import tuples
from hypothesis.strategies import uuids

from keks import _byte
from keks import Blob
from keks import Hexlet
from keks import Magic
from keks import Raw
from keks import TagTAI64NA
from keks import TAI64Base


TagTAI64NAb = _byte(TagTAI64NA)
junk_st = binary(max_size=8)
blobs_st = tuples(integers(1, 20), binary(max_size=60)).map(lambda x: Blob(*x))
unicode_allowed = characters(exclude_characters="\x00", exclude_categories=("Cs",))
text_st = text(alphabet=unicode_allowed, max_size=32)
mapkey_st = text(alphabet=unicode_allowed, min_size=1, max_size=8)
tai64na_st = tuples(integers(1, 100), integers(1, 100)).map(lambda x: Raw(
    TagTAI64NAb + (TAI64Base + x[0]).to_bytes(8, "big") + (x[1] + 1).to_bytes(8, "big")
))
magic_st = binary(min_size=0, max_size=12).filter(lambda x: b"\x00" not in x).map(Magic)
any_st = one_of(
    booleans(),
    integers(),
    just(0),
    just(-1),
    binary(max_size=32),
    text_st,
    none(),
    uuids().map(Hexlet),
    datetimes(),
    blobs_st,
    tai64na_st,
    magic_st,
)
everything_st = deferred(
    lambda: any_st |
    lists(everything_st, max_size=4) |
    dictionaries(mapkey_st, everything_st, max_size=4)
)
