# -*- coding: utf-8 -*-

"""Unit tests for encoding detection

Note that we're not necessarily testing how accurate the chardet/cchardet
libraries are. We're testing that our encoding detection function works.

Author: G.J.J. van den Burg
License: See the LICENSE file.

This file is part of CleverCSV.

"""

import os
import tempfile
import unittest

from dataclasses import dataclass

from typing import Any
from typing import List

from clevercsv._optional import import_optional_dependency
from clevercsv._types import AnyPath
from clevercsv.encoding import get_encoding
from clevercsv.write import writer


class EncodingTestCase(unittest.TestCase):
    @dataclass(frozen=True)
    class Instance:
        # Data to write to a file
        table: List[List[Any]]

        # Source encoding to use when writing
        source_encoding: str

        # Acceptable expected encodings from chardet
        chardet_encodings: set[str]

        # Acceptable expected encodings from cchardet
        cchardet_encodings: set[str]

    cases: List[Instance] = [
        Instance(
            table=[["Å", "B", "C"], [1, 2, 3], [4, 5, 6]],
            source_encoding="ISO-8859-1",
            chardet_encodings={"ISO-8859-1", "KOI8-R"},
            cchardet_encodings={"WINDOWS-1252"},
        ),
        Instance(
            table=[["A", "B", "C"], [1, 2, 3], [4, 5, 6]],
            source_encoding="ascii",
            chardet_encodings={"ascii"},
            cchardet_encodings={"ASCII"},
        ),
        Instance(
            table=[["亜唖", "娃阿", "哀愛"], [1, 2, 3], ["挨", "姶", "葵"]],
            source_encoding="ISO-2022-JP",
            chardet_encodings={"ISO-2022-JP"},
            cchardet_encodings={"ISO-2022-JP"},
        ),
    ]

    def setUp(self) -> None:
        self._tmpfiles: List[AnyPath] = []

    def tearDown(self) -> None:
        for f in self._tmpfiles:
            os.unlink(f)

    def _build_file(self, table: List[List[str]], encoding: str) -> str:
        tmpfd, tmpfname = tempfile.mkstemp(
            prefix="ccsv_",
            suffix=".csv",
        )
        tmpfp = os.fdopen(tmpfd, "w", newline=None, encoding=encoding)
        w = writer(tmpfp, dialect="excel")
        w.writerows(table)
        tmpfp.close()
        self._tmpfiles.append(tmpfname)
        return tmpfname

    def test_encoding_chardet(self) -> None:
        for case in self.cases:
            with self.subTest(encoding=case.source_encoding):
                tmpfname = self._build_file(case.table, case.source_encoding)
                detected = get_encoding(tmpfname, try_cchardet=False)
                self.assertIn(detected, case.chardet_encodings)

    def test_encoding_cchardet(self) -> None:
        try:
            _ = import_optional_dependency("cchardet")
        except ImportError:
            self.skipTest("Failed to import cchardet, skipping this test")

        for case in self.cases:
            with self.subTest(encoding=case.source_encoding):
                tmpfname = self._build_file(case.table, case.source_encoding)
                detected = get_encoding(tmpfname, try_cchardet=True)
                self.assertIn(
                    detected,
                    case.cchardet_encodings,
                )


if __name__ == "__main__":
    unittest.main()
