from datetime import datetime
from os import listdir
from os.path import abspath
from os.path import dirname
from os.path import join as path_join
from unittest import skipIf
from unittest import TestCase

from keks import _byte
from keks import Blob
from keks import Float
from keks import loads
from keks import NaN
from keks import Raw
from keks import TagTAI64
from keks import TagTAI64N
from keks import TagTAI64NA
from keks import TAI64Base


testsDir = dirname(abspath(__file__))
fuzzInputs = "fuzz-inputs"
fuzzInputsExists = False
try:
    if len(listdir(path_join(testsDir, fuzzInputs))) > 0:
        fuzzInputsExists = True
except FileNotFoundError:
    pass


def readInput(name: str) -> bytes:
    with open(path_join(testsDir, fuzzInputs, name), "rb") as fd:
        data = fd.read()
    ret, tail = loads(data)
    assert tail == b""
    return ret


class TestFuzzInputs(TestCase):
    """Check tcl/mk-fuzz-inputs output

    You have to create fuzz-inputs directory in tests and fill it up
    with mk-fuzz-inputs.
    """
    @skipIf(not fuzzInputsExists, "no fuzz-inputs/ found")
    def runTest(self) -> None:
        self.assertEqual(readInput("bin-empty"), b"")
        self.assertEqual(readInput("bin-1234"), b"\x01\x02\x03\x04")
        self.assertEqual(readInput("str-empty"), "")
        self.assertEqual(readInput("str-foo"), "foo")
        self.assertIs(readInput("true"), True)
        self.assertIs(readInput("false"), False)
        self.assertIs(readInput("nil"), None)
        self.assertEqual(readInput("int=0"), 0)
        self.assertEqual(readInput("int=-1"), -1)
        self.assertEqual(readInput("int=10"), 10)
        self.assertEqual(readInput("int=-10"), -10)
        self.assertEqual(readInput("int=500"), 500)
        self.assertEqual(readInput("int=-500"), -500)
        self.assertEqual(readInput("blob-empty"), Blob(l=2, v=b""))
        self.assertEqual(readInput("blob-f"), Blob(l=2, v=b"f"))
        self.assertEqual(readInput("blob-fo"), Blob(l=2, v=b"fo"))
        self.assertEqual(readInput("blob-foo"), Blob(l=2, v=b"foo"))
        self.assertEqual(readInput("list-empty"), [])
        self.assertEqual(readInput("list-nil"), [None])
        self.assertEqual(readInput("list-bool"), [True, False])
        self.assertEqual(readInput("map-empty"), dict())
        self.assertEqual(readInput("map-foo"), {"a": [None]})
        self.assertEqual(readInput("tai-utc0"), datetime(1970, 1, 1, 0, 0))
        self.assertEqual(readInput("tai-before"), datetime(1969, 12, 31, 23, 59, 49))
        self.assertEqual(readInput("tai-leap"), Raw(
            _byte(TagTAI64) + bytes.fromhex("40000000586846A4"),
        ))
        self.assertEqual(readInput("tai-ns"), Raw(_byte(TagTAI64N) + (
            (TAI64Base + 1234).to_bytes(8, "big") +
            (1234).to_bytes(4, "big")
        )))
        self.assertEqual(readInput("tai-as"), Raw(_byte(TagTAI64NA) + (
            (TAI64Base + 1234).to_bytes(8, "big") +
            2 * (1234).to_bytes(4, "big")
        )))
        self.assertIs(readInput("float=nan"), NaN)
        self.assertEqual(readInput("float=+inf"), float("+inf"))
        self.assertEqual(readInput("float=-inf"), float("-inf"))
        self.assertEqual(readInput("float=0"), 0.0)
        self.assertEqual(readInput("float=123,45"), Float(123, 45))
        self.assertEqual(readInput("float=-123,-45"), Float(-123, -45))
