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

"""
***************************************************************************
    ParametersTest
    ---------------------
    Date                 : March 2013
    Copyright            : (C) 2013 by Victor Olaya
    Email                : volayaf at gmail dot com
***************************************************************************
*                                                                         *
*   This program is free software; you can redistribute it and/or modify  *
*   it under the terms of the GNU General Public License as published by  *
*   the Free Software Foundation; either version 2 of the License, or     *
*   (at your option) any later version.                                   *
*                                                                         *
***************************************************************************
"""

__author__ = 'Victor Olaya'
__date__ = 'March 2013'
__copyright__ = '(C) 2013, Victor Olaya'

# This will get replaced with a git SHA1 when you do a git archive

__revision__ = '$Format:%H$'

from qgis.testing import start_app, unittest

from processing.core.parameters import (Parameter,
                                        ParameterBoolean,
                                        ParameterCrs,
                                        ParameterDataObject,
                                        ParameterExtent,
                                        ParameterFile,
                                        ParameterFixedTable,
                                        ParameterMultipleInput,
                                        ParameterNumber)

from qgis.core import (QgsRasterLayer,
                       QgsVectorLayer)

start_app()


class ParameterTest(unittest.TestCase):

    def testGetValueAsCommandLineParameter(self):
        parameter = Parameter('myName', 'myDesc')
        parameter.setValue(None)
        self.assertEqual(parameter.getValueAsCommandLineParameter(), "None")

        parameter.setValue("someValue")
        self.assertEqual(parameter.getValueAsCommandLineParameter(), 'someValue')

        parameter.setValue(123)
        self.assertEqual(parameter.getValueAsCommandLineParameter(), '123')


class ParameterBooleanTest(unittest.TestCase):

    def testSetValue(self):
        parameter = ParameterBoolean('myName', 'myDescription')
        self.assertEqual(parameter.value, None)
        parameter.setValue(False)
        self.assertEqual(parameter.value, False)
        parameter.setValue(True)
        self.assertEqual(parameter.value, True)

    def testDefault(self):
        parameter = ParameterBoolean('myName', 'myDescription', default=False, optional=True)
        self.assertEqual(parameter.value, False)
        parameter.setValue(None)
        self.assertEqual(parameter.value, None)

    def testOptional(self):
        optionalParameter = ParameterBoolean('myName', 'myDescription', default=False, optional=True)
        self.assertEqual(optionalParameter.value, False)
        optionalParameter.setValue(True)
        self.assertEqual(optionalParameter.value, True)
        self.assertTrue(optionalParameter.setValue(None))
        self.assertEqual(optionalParameter.value, None)

        requiredParameter = ParameterBoolean('myName', 'myDescription', default=False, optional=False)
        self.assertEqual(requiredParameter.value, False)
        requiredParameter.setValue(True)
        self.assertEqual(requiredParameter.value, True)
        self.assertFalse(requiredParameter.setValue(None))
        self.assertEqual(requiredParameter.value, True)


class ParameterCRSTest(unittest.TestCase):

    def testSetValue(self):
        parameter = ParameterCrs('myName', 'myDesc')
        self.assertTrue(parameter.setValue('EPSG:12003'))
        self.assertEqual(parameter.value, 'EPSG:12003')

    def testOptional(self):
        optionalParameter = ParameterCrs('myName', 'myDesc', default='EPSG:4326', optional=True)
        self.assertEqual(optionalParameter.value, 'EPSG:4326')
        optionalParameter.setValue('EPSG:12003')
        self.assertEqual(optionalParameter.value, 'EPSG:12003')
        self.assertTrue(optionalParameter.setValue(None))
        self.assertEqual(optionalParameter.value, None)

        requiredParameter = ParameterCrs('myName', 'myDesc', default='EPSG:4326', optional=False)
        self.assertEqual(requiredParameter.value, 'EPSG:4326')
        requiredParameter.setValue('EPSG:12003')
        self.assertEqual(requiredParameter.value, 'EPSG:12003')
        self.assertFalse(requiredParameter.setValue(None))
        self.assertEqual(requiredParameter.value, 'EPSG:12003')


class ParameterDataObjectTest(unittest.TestCase):

    def testGetValueAsCommandLineParameter(self):
        parameter = ParameterDataObject('myName', 'myDesc')
        parameter.setValue(None)
        self.assertEqual(parameter.getValueAsCommandLineParameter(), "None")

        parameter = ParameterDataObject('myName', 'myDesc')
        parameter.setValue("someFile.dat")
        self.assertEqual(parameter.getValueAsCommandLineParameter(), '"someFile.dat"')


class ParameterExtentTest(unittest.TestCase):

    def testSetValue(self):
        parameter = ParameterExtent('myName', 'myDesc')
        self.assertTrue(parameter.setValue('0,2,2,4'))
        self.assertEqual(parameter.value, '0,2,2,4')

    def testSetInvalidValue(self):
        parameter = ParameterExtent('myName', 'myDesc')
        self.assertFalse(parameter.setValue('0,2,0'))
        self.assertFalse(parameter.setValue('0,2,0,a'))

    def testOptional(self):
        optionalParameter = ParameterExtent('myName', 'myDesc', default='0,1,0,1', optional=True)
        self.assertEqual(optionalParameter.value, '0,1,0,1')
        optionalParameter.setValue('1,2,3,4')
        self.assertEqual(optionalParameter.value, '1,2,3,4')
        self.assertTrue(optionalParameter.setValue(None))
        # Extent is unique in that it will let you set `None`, whereas other
        # optional parameters become "default" when assigning None.
        self.assertEqual(optionalParameter.value, None)

        requiredParameter = ParameterExtent('myName', 'myDesc', default='0,1,0,1', optional=False)
        self.assertEqual(requiredParameter.value, '0,1,0,1')
        requiredParameter.setValue('1,2,3,4')
        self.assertEqual(requiredParameter.value, '1,2,3,4')
        self.assertFalse(requiredParameter.setValue(None))
        self.assertEqual(requiredParameter.value, '1,2,3,4')


class ParameterFileTest(unittest.TestCase):

    def testSetValue(self):
        parameter = ParameterFile('myName', 'myDesc')
        self.assertTrue(parameter.setValue('myFile.png'))
        self.assertEquals(parameter.value, 'myFile.png')

    def testOptional(self):
        optionalParameter = ParameterFile('myName', 'myDesc', optional=True)
        self.assertTrue(optionalParameter.setValue('myFile.png'))
        self.assertEquals(optionalParameter.value, 'myFile.png')

        self.assertTrue(optionalParameter.setValue(""))
        self.assertEquals(optionalParameter.value, '')

        self.assertTrue(optionalParameter.setValue(None))
        self.assertEquals(optionalParameter.value, None)

        requiredParameter = ParameterFile('myName', 'myDesc', optional=False)
        self.assertTrue(requiredParameter.setValue('myFile.png'))
        self.assertEquals(requiredParameter.value, 'myFile.png')

        self.assertFalse(requiredParameter.setValue(''))
        self.assertEquals(requiredParameter.value, 'myFile.png')

        self.assertFalse(requiredParameter.setValue('  '))
        self.assertEquals(requiredParameter.value, 'myFile.png')

        self.assertFalse(requiredParameter.setValue(None))
        self.assertEquals(requiredParameter.value, 'myFile.png')

    def testSetValueWithExtension(self):
        parameter = ParameterFile('myName', 'myDesc', ext="png")
        self.assertTrue(parameter.setValue('myFile.png'))
        self.assertEquals(parameter.value, 'myFile.png')

        self.assertFalse(parameter.setValue('myFile.bmp'))
        self.assertEquals(parameter.value, 'myFile.png')

    def testGetValueAsCommandLineParameter(self):
        parameter = ParameterFile('myName', 'myDesc')
        parameter.setValue('myFile.png')
        self.assertEqual(parameter.getValueAsCommandLineParameter(), '"myFile.png"')


class TestParameterFixedTable(unittest.TestCase):

    def testTableToString(self):
        table = [
            ['a0', 'a1', 'a2'],
            ['b0', 'b1', 'b2']
        ]
        self.assertEquals(ParameterFixedTable.tableToString(table), 'a0,a1,a2,b0,b1,b2')

        table = [['a0']]
        self.assertEquals(ParameterFixedTable.tableToString(table), 'a0')

        table = [[]]
        self.assertEquals(ParameterFixedTable.tableToString(table), '')

    def testSetStringValue(self):
        parameter = ParameterFixedTable('myName', 'myDesc')
        self.assertTrue(parameter.setValue('1,2,3'))
        self.assertEqual(parameter.value, '1,2,3')

    def testSet2DListValue(self):
        table = [
            ['a0', 'a1', 'a2'],
            ['b0', 'b1', 'b2']
        ]
        parameter = ParameterFixedTable('myName', 'myDesc')
        self.assertTrue(parameter.setValue(table))
        self.assertEqual(parameter.value, 'a0,a1,a2,b0,b1,b2')

    def testOptional(self):
        parameter = ParameterFixedTable('myName', 'myDesc', optional=True)
        self.assertTrue(parameter.setValue('1,2,3'))
        self.assertEqual(parameter.value, '1,2,3')

        self.assertTrue(parameter.setValue(None))
        self.assertEqual(parameter.value, None)

        parameter = ParameterFixedTable('myName', 'myDesc', optional=False)
        self.assertFalse(parameter.setValue(None))
        self.assertEqual(parameter.value, None)

        self.assertTrue(parameter.setValue('1,2,3'))
        self.assertEqual(parameter.value, '1,2,3')

        self.assertFalse(parameter.setValue(None))
        self.assertEqual(parameter.value, '1,2,3')


class ParameterMultipleInputTest(unittest.TestCase):

    def testOptional(self):
        parameter = ParameterMultipleInput('myName', 'myDesc', optional=True)
        self.assertTrue(parameter.setValue('myLayerFile.shp'))
        self.assertEqual(parameter.value, 'myLayerFile.shp')

        self.assertTrue(parameter.setValue(None))
        self.assertEqual(parameter.value, None)

        parameter = ParameterMultipleInput('myName', 'myDesc', optional=False)
        self.assertFalse(parameter.setValue(None))
        self.assertEqual(parameter.value, None)

        self.assertTrue(parameter.setValue("myLayerFile.shp"))
        self.assertEqual(parameter.value, "myLayerFile.shp")

        self.assertFalse(parameter.setValue(None))
        self.assertEqual(parameter.value, "myLayerFile.shp")

    def testGetAsStringWhenRaster(self):
        parameter = ParameterMultipleInput('myName', 'myDesc', datatype=ParameterMultipleInput.TYPE_RASTER)

        # With Path
        self.assertEqual(parameter.getAsString('/some/path'), '/some/path')

        # With Layer
        layer = QgsRasterLayer('/path/to/myRaster.tif', 'myRaster')
        self.assertEqual(parameter.getAsString(layer), '/path/to/myRaster.tif')

        # TODO With Layer Name, instead of Layer object

    def testGetAsStringWhenFile(self):
        parameter = ParameterMultipleInput('myName', 'myDesc', datatype=ParameterMultipleInput.TYPE_FILE)
        self.assertEqual(parameter.getAsString('/some/path'), '/some/path')

    def testGetAsStringWhenVector(self):
        parameter = ParameterMultipleInput('myName', 'myDesc', datatype=ParameterMultipleInput.TYPE_VECTOR_ANY)

        # With Path
        self.assertEqual(parameter.getAsString('/some/path'), '/some/path')

        # With Layer
        layer = QgsVectorLayer('/path/to/myVector.shp', 'myVector', 'memory')
        self.assertEqual(parameter.getAsString(layer), '/path/to/myVector.shp')

        # TODO With Layer Name, instead of Layer object


class ParameterNumberTest(unittest.TestCase):

    def testSetValue(self):
        parameter = ParameterNumber('myName', 'myDescription')
        self.assertTrue(parameter.setValue(5))
        self.assertEquals(parameter.value, 5)

    def testSetValueOnlyValidNumbers(self):
        parameter = ParameterNumber('myName', 'myDescription')
        self.assertFalse(parameter.setValue('not a number'))
        self.assertEqual(parameter.value, None)

    def testMaxValue(self):
        parameter = ParameterNumber('myName', 'myDescription', maxValue=10)
        self.assertFalse(parameter.setValue(11))
        self.assertEqual(parameter.value, None)
        self.assertTrue(parameter.setValue(10))
        self.assertEqual(parameter.value, 10)

    def testMinValue(self):
        parameter = ParameterNumber('myName', 'myDescription', minValue=3)
        self.assertFalse(parameter.setValue(1))
        self.assertEqual(parameter.value, None)
        self.assertFalse(parameter.setValue(-2))
        self.assertEqual(parameter.value, None)
        self.assertTrue(parameter.setValue(3))
        self.assertEqual(parameter.value, 3)

    def testOptional(self):
        optionalParameter = ParameterNumber('myName', 'myDescription', default=1.0, optional=True)
        self.assertEqual(optionalParameter.value, 1.0)
        optionalParameter.setValue(5)
        self.assertEqual(optionalParameter.value, 5)
        self.assertTrue(optionalParameter.setValue(None))
        self.assertEqual(optionalParameter.value, None)

        requiredParameter = ParameterNumber('myName', 'myDescription', default=1.0, optional=False)
        self.assertEqual(requiredParameter.value, 1.0)
        requiredParameter.setValue(5)
        self.assertEqual(requiredParameter.value, 5)
        self.assertFalse(requiredParameter.setValue(None))
        self.assertEqual(requiredParameter.value, 5)


def suite():
    suite = unittest.makeSuite(ParametersTest, 'test')
    return suite


def runtests():
    result = unittest.TestResult()
    testsuite = suite()
    testsuite.run(result)
    return result

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