# (c) cavaliba.com - tests / loader detect_csv_delimiter()

"""
The heuristic behind the Import Tool's "Auto-detect" delimiter: keep the first
of |, ; , that separates the same number of columns on every line inspected.
It must never guess - an undetectable file has to come back as None so the form
can ask the user instead of importing one wide column.
"""

from django.test import TestCase

from app_data.loader import detect_csv_delimiter


def _lines(text):
    return text.splitlines()


class DetectCsvDelimiterTest(TestCase):
    def test_comma(self):
        found = detect_csv_delimiter(_lines("classname,keyname\nsite,GAVLE\nsite,MALMO\n"))
        self.assertEqual(found, ",")

    def test_semicolon(self):
        found = detect_csv_delimiter(_lines("classname;keyname\nsite;GAVLE\nsite;MALMO\n"))
        self.assertEqual(found, ";")

    def test_pipe(self):
        found = detect_csv_delimiter(_lines("classname|keyname\nsite|GAVLE\nsite|MALMO\n"))
        self.assertEqual(found, "|")

    def test_pipe_wins_over_a_comma_in_the_data(self):
        """A ,-containing value must not outvote the real delimiter."""

        found = detect_csv_delimiter(
            _lines("classname|keyname|town\nsite|GAVLE|Gavle, SE\nsite|MALMO|Malmo, SE\n")
        )
        self.assertEqual(found, "|")

    def test_semicolon_wins_over_a_comma_in_the_data(self):
        found = detect_csv_delimiter(
            _lines("classname;keyname;town\nsite;GAVLE;Gavle, SE\nsite;MALMO;Malmo, SE\n")
        )
        self.assertEqual(found, ";")

    def test_a_delimiter_inside_quotes_does_not_count(self):
        found = detect_csv_delimiter(
            _lines('classname,keyname,town\nsite,GAVLE,"Gavle;SE"\nsite,MALMO,"Malmo;SE"\n')
        )
        self.assertEqual(found, ",")

    def test_header_only(self):
        """One line is enough: consistency holds trivially."""

        self.assertEqual(detect_csv_delimiter(_lines("classname;keyname\n")), ";")

    def test_blank_lines_are_ignored(self):
        found = detect_csv_delimiter(_lines("classname;keyname\n\nsite;GAVLE\n\n"))
        self.assertEqual(found, ";")

    def test_single_column_file_accepts_any_delimiter(self):
        """Nothing to separate, so every delimiter parses the same - answering
        "," is a fact rather than a guess."""

        self.assertEqual(detect_csv_delimiter(_lines("keyname\nGAVLE\nMALMO\n")), ",")

    def test_inconsistent_counts_are_not_detected(self):
        """A ragged file could be a broken ;-file or a ,-file - refuse to pick."""

        found = detect_csv_delimiter(_lines("a,b\nc,d,e\nf\n"))
        self.assertIsNone(found)

    def test_tab_delimited_is_not_detected(self):
        """Tab is not offered by the form, so it must not be silently accepted
        as a single-column file either."""

        found = detect_csv_delimiter(_lines("classname\tkeyname\nsite\tGAVLE,SE\n"))
        self.assertIsNone(found)

    def test_empty_input(self):
        self.assertIsNone(detect_csv_delimiter([]))
        self.assertIsNone(detect_csv_delimiter(None))
        self.assertIsNone(detect_csv_delimiter(["", "   "]))

    def test_only_the_first_lines_are_inspected(self):
        """A file whose 6th line is ragged still detects: the sniff window is
        the header plus a few rows."""

        text = "a;b\nc;d\ne;f\ng;h\ni;j\nk;l;m\n"
        self.assertEqual(detect_csv_delimiter(_lines(text)), ";")
