import unittest
import csv
import io
from AnyQt.QtCore import Qt

from AnyQt.QtWidgets import QComboBox, QWidget
from AnyQt.QtTest import QSignalSpy, QTest

from Orange.widgets.utils import textimport
from Orange.widgets.tests.base import GuiTest
from Orange.widgets.utils.textimport import TablePreview, TablePreviewModel

ColumnTypes = textimport.ColumnType

DATA1 = b",A,B,C"
DATA2 = b""
DATA3 = b"A"
DATA4 = b'A, B, C, D\n' \
        b'a, 1, 2, *\n' \
        b'b, 2, 4, *'
DATA5 = b'a\tb\n' * 1000


class OptionsWidgetTests(GuiTest):
    def test_options_widget(self):
        w = textimport.CSVOptionsWidget()
        schanged = QSignalSpy(w.optionsChanged)
        sedited = QSignalSpy(w.optionsEdited)
        w.setDialect(csv.excel())
        self.assertEqual(len(schanged), 1)
        self.assertEqual(len(sedited), 0)
        w.setSelectedEncoding("iso8859-1")

        self.assertEqual(len(schanged), 2)
        self.assertEqual(len(sedited), 0)

        d = w.dialect()
        self.assertEqual(d.delimiter, csv.excel.delimiter)
        self.assertEqual(d.doublequote, csv.excel.doublequote)
        self.assertEqual(w.encoding(), "iso8859-1")

        d = textimport.Dialect("a", "b", "c", True, True)
        w.setDialect(d)

        cb = w.findChild(QComboBox, "delimiter-combo-box")
        self.assertEqual(cb.currentIndex(),
                         textimport.CSVOptionsWidget.DelimiterOther)
        le = w.findChild(QWidget, "custom-delimiter-edit")
        self.assertEqual(le.text(), "a")

        cb = w.findChild(QWidget, "quote-edit-combo-box")
        self.assertEqual(cb.currentText(), "b")
        d1 = w.dialect()
        self.assertEqual(d.delimiter, d1.delimiter)
        self.assertEqual(d.quotechar, d1.quotechar)


class ImportWidgetTest(GuiTest):
    def test_import_widget(self):
        w = textimport.CSVImportWidget()
        w.setDialect(csv.excel())
        w.setSampleContents(io.BytesIO(DATA1))
        view = w.dataview
        model = view.model()
        self.assertEqual(model.columnCount(), 4)
        self.assertEqual(model.rowCount(), 1)
        self.assertEqual(model.canFetchMore(), False)
        w.setSampleContents(io.BytesIO(DATA2))
        model = view.model()
        self.assertEqual(model.columnCount(), 0)
        self.assertEqual(model.rowCount(), 0)
        self.assertEqual(model.canFetchMore(), False)
        w.setSampleContents(io.BytesIO(DATA4))
        model = view.model()
        self.assertEqual(model.columnCount(), 4)
        self.assertEqual(model.rowCount(), 3)

        types = {
            0: ColumnTypes.Categorical,
            1: ColumnTypes.Numeric,
            2: ColumnTypes.Text,
            3: ColumnTypes.Time,
        }
        w.setColumnTypes(types)
        self.assertEqual(w.columnTypes(), types)
        rs = w.rowStates()
        self.assertEqual(rs, {})
        w.setStateForRow(0, textimport.TablePreview.Header)
        w.setRowStates({0: textimport.TablePreview.Header})
        self.assertEqual(w.rowStates(), {0: textimport.TablePreview.Header})
        w.setStateForRow(1, textimport.TablePreview.Skipped)
        view.grab()

        w.setSampleContents(io.BytesIO(DATA5))
        model = view.model()
        self.assertEqual(model.columnCount(), 1)
        w.setDialect(csv.excel_tab())
        w.setSampleContents(io.BytesIO(DATA5))
        model = view.model()
        self.assertEqual(model.columnCount(), 2)
        self.assertTrue(model.canFetchMore())
        rows = model.rowCount()
        spy = QSignalSpy(model.rowsInserted)
        model.fetchMore()
        self.assertGreater(model.rowCount(), rows)
        self.assertEqual(len(spy), 1)

    def test_preview_view(self):
        w = TablePreview()
        model = TablePreviewModel()
        model.setPreviewStream(csv.reader(io.StringIO(DATA4.decode('utf-8'))))
        w.setModel(model)
        QTest.mouseClick(w.verticalHeader().viewport(), Qt.LeftButton)
        self.assertEqual(w.selectionBehavior(), TablePreview.SelectRows)
        QTest.mouseClick(w.horizontalHeader().viewport(), Qt.LeftButton)
        self.assertEqual(w.selectionBehavior(), TablePreview.SelectColumns)

        QTest.mouseClick(w.verticalHeader().viewport(), Qt.LeftButton)
        self.assertEqual(w.selectionBehavior(), TablePreview.SelectRows)
        QTest.mouseClick(w.viewport(), Qt.LeftButton)
        self.assertEqual(w.selectionBehavior(), TablePreview.SelectColumns)


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