from Products.validation import validation as validationService
from bika.lims.testing import BIKA_INTEGRATION_TESTING
from bika.lims.tests.base import BikaIntegrationTestCase
from plone.app.testing import login
from plone.app.testing import TEST_USER_NAME
import unittest


class Tests(BikaIntegrationTestCase):

    layer = BIKA_INTEGRATION_TESTING

    def test_UniqueFieldValidator(self):
        login(self.portal, TEST_USER_NAME)

        clients = self.portal.clients
        client1 = clients['client-2']
        self.assertEqual(
            client1.schema.get('Name').validate('Happy Hills', client1),
            u"Validation failed: 'Happy Hills' is not unique")
        self.assertEqual(None, client1.schema.get('title').validate('Another Client', client1))

    def test_ServiceKeywordValidator(self):
        login(self.portal, TEST_USER_NAME)

        services = self.portal.bika_setup.bika_analysisservices
        service1 = services['analysisservice-1']

        self.assertEqual(
            service1.schema.get('Keyword').validate('', service1),
            u'Analysis Keyword is required, please correct.')
        self.assertEqual(
            service1.schema.get('Keyword').validate('&', service1),
            u'Validation failed: keyword contains invalid characters')
        self.assertEqual(
            service1.schema.get('Keyword').validate('Ca', service1),
            u"Validation failed: 'Ca': This keyword is already in use by service 'Calcium'")
        self.assertEqual(
            service1.schema.get('Keyword').validate('TV', service1),
            u"Validation failed: 'TV': This keyword is already in use by calculation 'Titration'")
        self.assertEqual(None, service1.schema.get('Keyword').validate('VALID_KW', service1))

    def test_InterimFieldsValidator(self):
        login(self.portal, TEST_USER_NAME)

        calcs = self.portal.bika_setup.bika_calculations
        # Titration
        calc1 = calcs['calculation-1']

        interim_fields = []
        self.portal.REQUEST.form['InterimFields'] = interim_fields
        self.portal.REQUEST['validated'] = None
        self.assertEqual(None, calc1.schema.get('InterimFields').validate(interim_fields, calc1, REQUEST=self.portal.REQUEST))

        interim_fields = [{'keyword': '&', 'title': 'Titration Volume', 'unit': '', 'default': ''}, ]
        self.portal.REQUEST.form['InterimFields'] = interim_fields
        self.portal.REQUEST['validated'] = None
        self.assertEqual(
            calc1.schema.get('InterimFields').validate(interim_fields, calc1, REQUEST=self.portal.REQUEST),
            u"Validation failed: keyword contains invalid characters")

        interim_fields = [{'keyword': 'XXX', 'title': 'Gross Mass', 'unit': '', 'default': ''},
                          {'keyword': 'TV', 'title': 'Titration Volume', 'unit': '', 'default': ''}]
        self.portal.REQUEST.form['InterimFields'] = interim_fields
        self.portal.REQUEST['validated'] = None
        self.assertEqual(
            calc1.schema.get('InterimFields').validate(interim_fields, calc1, REQUEST=self.portal.REQUEST),
            u"Validation failed: column title 'Gross Mass' must have keyword 'GM'")

        interim_fields = [{'keyword': 'GM', 'title': 'XXX', 'unit': '', 'default': ''},
                          {'keyword': 'TV', 'title': 'Titration Volume', 'unit': '', 'default': ''}]
        self.portal.REQUEST.form['InterimFields'] = interim_fields
        self.portal.REQUEST['validated'] = None
        self.assertEqual(
            calc1.schema.get('InterimFields').validate(interim_fields, calc1, REQUEST=self.portal.REQUEST),
            u"Validation failed: keyword 'GM' must have column title 'Gross Mass'")

        interim_fields = [{'keyword': 'TV', 'title': 'Titration Volume', 'unit': '', 'default': ''},
                          {'keyword': 'TV', 'title': 'Titration Volume', 'unit': '', 'default': ''}]
        self.portal.REQUEST.form['InterimFields'] = interim_fields
        self.portal.REQUEST['validated'] = None
        self.assertEqual(
            calc1.schema.get('InterimFields').validate(interim_fields, calc1, REQUEST=self.portal.REQUEST),
            u"Validation failed: 'TV': duplicate keyword")

        interim_fields = [{'keyword': 'TV', 'title': 'Titration Volume', 'unit': '', 'default': ''},
                          {'keyword': 'TF', 'title': 'Titration Volume', 'unit': '', 'default': ''}]
        self.portal.REQUEST.form['InterimFields'] = interim_fields
        self.portal.REQUEST['validated'] = None
        self.assertEqual(
            calc1.schema.get('InterimFields').validate(interim_fields, calc1, REQUEST=self.portal.REQUEST),
            u"Validation failed: 'Titration Volume': duplicate title")

        interim_fields = [{'keyword': 'Ca', 'title': 'Titration Volume', 'unit': '', 'default': ''},
                          {'keyword': 'TF', 'title': 'Titration Factor', 'unit': '', 'default': ''}]
        self.portal.REQUEST.form['InterimFields'] = interim_fields
        self.portal.REQUEST['validated'] = None
        self.assertEqual(
            calc1.schema.get('InterimFields').validate(interim_fields, calc1, REQUEST=self.portal.REQUEST),
            u"Validation failed: 'Ca': This keyword is already in use by service 'Calcium'")

        interim_fields = [{'keyword': 'TV', 'title': 'Titration Volume', 'unit': '', 'default': ''},
                          {'keyword': 'TF', 'title': 'Titration Factor', 'unit': '', 'default': ''}]
        self.portal.REQUEST.form['InterimFields'] = interim_fields
        self.portal.REQUEST['validated'] = None
        self.assertEqual(None, calc1.schema.get('InterimFields').validate(interim_fields, calc1, REQUEST=self.portal.REQUEST))

    def test_FormulaValidator(self):
        login(self.portal, TEST_USER_NAME)

        v = validationService.validatorFor('formulavalidator')
        calcs = self.portal.bika_setup.bika_calculations
        calc1 = calcs['calculation-1']

        interim_fields = [{'keyword': 'TV', 'title': 'Titration Volume', 'unit': '', 'default': ''},
                          {'keyword': 'TF', 'title': 'Titration Factor', 'unit': '', 'default': ''}]
        self.portal.REQUEST.form['InterimFields'] = interim_fields

        formula = "[TV] * [TF] * [Wrong]"
        self.failUnlessEqual(
            v(formula, instance=calc1, field=calc1.schema.get('Formula'), REQUEST=self.portal.REQUEST),
            "Validation failed: Keyword 'Wrong' is invalid")

        formula = "[TV] * [TF]"
        self.assertEqual(True, v(formula, instance=calc1, field=calc1.schema.get('Formula'), REQUEST=self.portal.REQUEST))

    def test_CoordinateValidator(self):
        login(self.portal, TEST_USER_NAME)

        sp = self.portal.bika_setup.bika_samplepoints['samplepoint-1']

        latitude = {'degrees': '!', 'minutes': '2', 'seconds': '3', 'bearing': 'N'}
        self.portal.REQUEST.form['Latitude'] = latitude
        val = sp.schema.get('Latitude').validate(latitude, sp)
        self.assertEqual(True, u"Validation failed: degrees must be numeric" in val)

        latitude = {'degrees': '0', 'minutes': '!', 'seconds': '3', 'bearing': 'N'}
        self.portal.REQUEST.form['Latitude'] = latitude
        self.portal.REQUEST['validated'] = None
        val = sp.schema.get('Latitude').validate(latitude, sp)
        self.assertEqual(True, u"Validation failed: minutes must be numeric" in val)

        latitude = {'degrees': '0', 'minutes': '0', 'seconds': '!', 'bearing': 'N'}
        self.portal.REQUEST.form['Latitude'] = latitude
        self.portal.REQUEST['validated'] = None
        val = sp.schema.get('Latitude').validate(latitude, sp)
        self.assertEqual(True, u"Validation failed: seconds must be numeric" in val)

        latitude = {'degrees': '0', 'minutes': '60', 'seconds': '0', 'bearing': 'N'}
        self.portal.REQUEST.form['Latitude'] = latitude
        self.portal.REQUEST['validated'] = None
        val = sp.schema.get('Latitude').validate(latitude, sp)
        self.assertEqual(True, u"Validation failed: minutes must be 0 - 59" in val)

        latitude = {'degrees': '0', 'minutes': '0', 'seconds': '60', 'bearing': 'N'}
        self.portal.REQUEST.form['Latitude'] = latitude
        self.portal.REQUEST['validated'] = None
        val = sp.schema.get('Latitude').validate(latitude, sp)
        self.assertEqual(True, u"Validation failed: seconds must be 0 - 59" in val)

        # latitude specific

        latitude = {'degrees': '91', 'minutes': '0', 'seconds': '0', 'bearing': 'N'}
        self.portal.REQUEST.form['Latitude'] = latitude
        self.portal.REQUEST['validated'] = None
        val = sp.schema.get('Latitude').validate(latitude, sp)
        self.assertEqual(True, u"Validation failed: degrees must be 0 - 90" in val)

        latitude = {'degrees': '90', 'minutes': '1', 'seconds': '0', 'bearing': 'N'}
        self.portal.REQUEST.form['Latitude'] = latitude
        self.portal.REQUEST['validated'] = None
        val = sp.schema.get('Latitude').validate(latitude, sp)
        self.assertEqual(True, u"Validation failed: degrees is 90; minutes must be zero" in val)

        latitude = {'degrees': '90', 'minutes': '0', 'seconds': '1', 'bearing': 'N'}
        self.portal.REQUEST.form['Latitude'] = latitude
        self.portal.REQUEST['validated'] = None
        val = sp.schema.get('Latitude').validate(latitude, sp)
        self.assertEqual(True, u"Validation failed: degrees is 90; seconds must be zero" in val)

        latitude = {'degrees': '90', 'minutes': '0', 'seconds': '0', 'bearing': 'E'}
        self.portal.REQUEST.form['Latitude'] = latitude
        self.portal.REQUEST['validated'] = None
        val = sp.schema.get('Latitude').validate(latitude, sp)
        self.assertEqual(True, u"Validation failed: Bearing must be N/S" in val)

        # longitude specific

        longitude = {'degrees': '181', 'minutes': '0', 'seconds': '0', 'bearing': 'E'}
        self.portal.REQUEST.form['Longitude'] = longitude
        self.portal.REQUEST['validated'] = None
        val = sp.schema.get('Longitude').validate(longitude, sp)
        self.assertEqual(True, u"Validation failed: degrees must be 0 - 180" in val)

        longitude = {'degrees': '180', 'minutes': '1', 'seconds': '0', 'bearing': 'E'}
        self.portal.REQUEST.form['Longitude'] = longitude
        self.portal.REQUEST['validated'] = None
        val = sp.schema.get('Longitude').validate(longitude, sp)
        self.assertEqual(True, u"Validation failed: degrees is 180; minutes must be zero" in val)

        longitude = {'degrees': '180', 'minutes': '0', 'seconds': '1', 'bearing': 'E'}
        self.portal.REQUEST.form['Longitude'] = longitude
        self.portal.REQUEST['validated'] = None
        val = sp.schema.get('Longitude').validate(longitude, sp)
        self.assertEqual(True, u"Validation failed: degrees is 180; seconds must be zero" in val)

        longitude = {'degrees': '0', 'minutes': '0', 'seconds': '0', 'bearing': 'N'}
        self.portal.REQUEST.form['Longitude'] = longitude
        self.portal.REQUEST['validated'] = None
        val = sp.schema.get('Longitude').validate(longitude, sp)
        self.assertEqual(True, u"Validation failed: Bearing must be E/W" in val)

        longitude = {'degrees': '1', 'minutes': '1', 'seconds': '1', 'bearing': 'E'}
        self.portal.REQUEST.form['Longitude'] = longitude
        self.portal.REQUEST['validated'] = None
        self.assertEqual(None, sp.schema.get('Longitude').validate(longitude, sp))


def test_suite():
    suite = unittest.TestSuite()
    suite.addTest(unittest.makeSuite(Tests))
    suite.layer = BIKA_INTEGRATION_TESTING
    return suite
