import xlrd

from copy import deepcopy
from seantis.agencies import tests
from seantis.agencies.browser.xlsexport import TITLES_ORGANIZATION
from seantis.agencies.browser.xlsexport import TITLES_REGISTER
from StringIO import StringIO
from xlwt import Workbook
from zExceptions import Unauthorized


class TestImportExport(tests.BrowserTestCase):

    def setUp(self):
        super(TestImportExport, self).setUp()
        self.organizations = [
            [u'0', u'1,2', u'Organizations', u'des_0', u'port_0', 0],
            [u'1', u'', u'org_1', u'des_1', u'port_1', 0],
            [u'2', u'3', u'org_2', u'des_2', u'port_2', 0],
            [u'3', u'', u'org_3', u'des_3', u'port_3', 1]
        ]
        self.people = [
            [str(prefix) + '_' + field for field in TITLES_REGISTER]
            for prefix in range(3)
        ]
        self.people[0][-1] = u'(0)(role)(2006)(*)(3)//'
        self.people[1][-1] = u'(1)()()()(7)// (0)()()()(2)//(3)()()()(7)'
        self.people[2][-1] = u'(2)(role)()(2000)(2)//(3)()(*)()(8)'

    def create_test_workbook(self, filehandle, organizations=None,
                             people=None):
        if organizations is None:
            organizations = self.organizations
        if people is None:
            people = self.people

        book = Workbook(encoding='utf-8')
        sheet = book.add_sheet(u'Organizations')
        for index, cell in enumerate(TITLES_ORGANIZATION):
            sheet.row(0).write(index, cell)
        for row, organization in enumerate(organizations):
            for index, cell in enumerate(organization):
                sheet.row(row + 1).write(index, cell)
        sheet = book.add_sheet(u'People')
        for index, cell in enumerate(TITLES_REGISTER):
            sheet.row(0).write(index, cell)
        for row, organization in enumerate(people):
            for index, cell in enumerate(organization):
                sheet.row(row + 1).write(index, cell)
        book.save(filehandle)

    def test_access(self):
        browser = self.new_browser()
        self.assertRaises(Unauthorized, browser.open, '/export-agencies')
        self.assertRaises(Unauthorized, browser.open, '/import-agencies')

    def test_export_empty(self):
        browser = self.new_admin_browser()
        browser.open('/export-agencies')
        self.assertEquals(browser.contents, '')
        self.assertEquals(browser.headers['Content-disposition'], 'export.xls')
        self.assertEquals(browser.headers['Content-Type'], 'application/xls')
        self.assertEquals(browser.headers['Content-Length'], '0')

    def test_import_export(self):
        filehandle = StringIO()
        self.create_test_workbook(filehandle)
        xls_file = filehandle.getvalue()
        filehandle.close()

        # import
        browser = self.new_admin_browser()
        browser.open('/import-agencies')
        widget = browser.getControl(name='form.widgets.xls_file')
        widget.add_file(xls_file, 'application/xls', 'import.xls')
        browser.getControl('Import').click()

        # export
        browser.open('/export-agencies')
        self.assertEquals(browser.headers['Content-disposition'], 'export.xls')
        self.assertEquals(browser.headers['Content-Type'], 'application/xls')
        self.assertTrue(int(browser.headers['Content-Length']) > 0)

        # compare
        workbook = xlrd.open_workbook(file_contents=browser.contents)
        sheets = workbook.sheets()
        self.assertEquals(len(sheets), 2)
        self.assertEquals(sheets[0].name, u'Organizations')
        self.assertEquals(sheets[0].ncols, len(TITLES_ORGANIZATION))
        self.assertEquals(sheets[0].nrows, 5)

        for row, content in enumerate(self.organizations):
            self.assertEquals([cell.value for cell in sheets[0].row(row + 1)],
                              content)

        self.assertEquals(sheets[1].name, u'People')
        self.assertEquals(sheets[1].ncols, len(TITLES_REGISTER))
        self.assertEquals(sheets[1].nrows, 4)
        for row, content in enumerate(self.people):
            self.assertEquals(
                [cell.value for cell in sheets[1].row(row + 1)[:-1]],
                content[:-1]
            )

        # roles are slightly different: position starts at zero, order is
        # random
        self.assertEquals(u'(0)(role)(2006)(*)(1)',
                          sheets[1].cell(1, -1).value)
        self.assertTrue(u'(1)()()()(0)', sheets[1].cell(2, -1).value)
        self.assertTrue(u'(3)()()()(0)', sheets[1].cell(2, -1).value)
        self.assertTrue(u'(0)()()()(0)', sheets[1].cell(2, -1).value)
        self.assertTrue(u'(2)(role)()()(0)', sheets[1].cell(3, -1).value)
        self.assertTrue(u'(3)()()(*)(1)', sheets[1].cell(3, -1).value)

        # browse imported items
        browser.open('/organizations')
        self.assertIn('des_0', browser.contents)
        self.assertIn('port_0', browser.contents)
        self.assertIn('org_1', browser.contents)
        self.assertIn('org_2', browser.contents)
        self.assertNotIn('org_3', browser.contents)

        browser.open('/organizations/org_1')
        self.assertIn('des_1', browser.contents)
        self.assertIn('port_1', browser.contents)
        self.assertNotIn('org_2', browser.contents)
        self.assertNotIn('org_3', browser.contents)

        browser.open('/organizations/org_2')
        self.assertIn('des_2', browser.contents)
        self.assertIn('port_2', browser.contents)
        self.assertNotIn('org_1', browser.contents)
        self.assertIn('org_3', browser.contents)

        browser.open('/organizations/org_2/org_3')
        self.assertIn('des_3', browser.contents)
        self.assertIn('port_3', browser.contents)

    def test_import_errors(self):
        browser = self.new_admin_browser()

        # missing file
        browser.open('/import-agencies')
        browser.getControl('Import').click()
        self.assertIn('Required input is missing', browser.contents)

        # invalid file
        browser.open('/import-agencies')
        widget = browser.getControl(name='form.widgets.xls_file')
        widget.add_file('stuff', 'application/xls', 'import.xls')
        browser.getControl('Import').click()
        self.assertIn('Invalid XLS file', browser.contents)

        # error in register sheet
        people = deepcopy(self.people)
        people[1][-1] = u'(1))()()(7)// (0aa()()(2)//(3)()()()(7)//'
        filehandle = StringIO()
        self.create_test_workbook(filehandle, people=people)
        xls_file = filehandle.getvalue()
        filehandle.close()

        browser.open('/import-agencies')
        widget = browser.getControl(name='form.widgets.xls_file')
        widget.add_file(xls_file, 'application/xls', 'import.xls')
        browser.getControl('Import').click()

        self.assertIn('Invalid row 2 in sheet People', browser.contents)

        # error in organization sheet
        organizations = deepcopy(self.organizations)
        organizations[0][2] = u'Urganizations'
        organizations[2][0] = u'1'
        filehandle = StringIO()
        self.create_test_workbook(filehandle, organizations=organizations)
        xls_file = filehandle.getvalue()
        filehandle.close()

        browser.open('/import-agencies')
        widget = browser.getControl(name='form.widgets.xls_file')
        widget.add_file(xls_file, 'application/xls', 'import.xls')
        browser.getControl('Import').click()
        self.assertIn('Top level organizations not found', browser.contents)
        self.assertIn('Invalid row 3 in sheet Organizations', browser.contents)
