# -*- coding: utf-8 -*-
from grass.gunittest.case import TestCase
from grass.gunittest.main import test
from grass.gunittest.gmodules import SimpleModule


class TestVsurfrst(TestCase):

    elevation = 'elevation'
    elevation_attrib = 'elevation_attrib'
    elevation_threads = 'elevation_threads'
    slope = 'slope'
    aspect = 'aspect'
    pcurvature = 'pcurvature'
    tcurvature = 'tcurvature'
    mcurvature = 'mcurvature'
    deviations = 'deviations'
    cvdev = 'cvdev'
    treeseg = 'treeseg'
    overwin = 'overwin'

    @classmethod
    def setUpClass(cls):
        cls.use_temp_region()
        cls.runModule('g.region', vector='elev_points', res=1)
        cls.runModule('v.to.3d', input='elev_points', type='point',
                      output='elev_points3d', column='value', overwrite=True)

    @classmethod
    def tearDownClass(cls):
        cls.del_temp_region()
        cls.runModule('g.remove', type=['raster', 'vector'],
                      name=['elev_points3d', cls.elevation, cls.elevation_threads,
                            cls.elevation_attrib, cls.slope, cls.aspect, cls.pcurvature,
                            cls.tcurvature, cls.mcurvature, cls.deviations,
                            cls.cvdev, cls.treeseg, cls.overwin], flags='f')

    def setUp(self):
        self.vsurfrst = SimpleModule('v.surf.rst', input='elev_points3d', npmin=100,
                                     elevation=self.elevation, overwrite=True)

    def test_more_threads(self):
        self.assertModule(self.vsurfrst)
        try:
            self.vsurfrst.inputs['nprocs'].value = 4
            self.vsurfrst.outputs.elevation = self.elevation_threads
            self.assertModule(self.vsurfrst)
            self.assertRastersNoDifference(self.elevation, self.elevation_threads, precision=1e-8)
        except KeyError:
            # original version of v.surf.rst without parallel processing
            return

    def test_run_outputs(self):
        self.vsurfrst.outputs.slope = self.slope
        self.vsurfrst.outputs.aspect = self.aspect
        self.vsurfrst.outputs.pcurvature = self.pcurvature
        self.vsurfrst.outputs.tcurvature = self.tcurvature
        self.vsurfrst.outputs.mcurvature = self.mcurvature
        self.vsurfrst.outputs.deviations = self.deviations
        self.vsurfrst.outputs.treeseg = self.treeseg
        self.vsurfrst.outputs.overwin = self.overwin

        self.assertModule(self.vsurfrst)
        self.assertRasterExists(name=self.elevation)
        self.assertRasterExists(name=self.slope)
        self.assertRasterExists(name=self.aspect)
        self.assertRasterExists(name=self.pcurvature)
        self.assertRasterExists(name=self.tcurvature)
        self.assertRasterExists(name=self.mcurvature)
        self.assertVectorExists(name=self.deviations)
        self.assertVectorExists(name=self.treeseg)
        self.assertVectorExists(name=self.overwin)
        values = 'min=103.973861694336\nmax=131.529937744141\nmean=120.774013407641'
        self.assertRasterFitsUnivar(raster=self.elevation, reference=values, precision=1e-8)
        # slope
        values = 'min=0.00417369091883302\nmax=15.4391813278198\nmean=3.32303673469512'
        self.assertRasterFitsUnivar(raster=self.slope, reference=values, precision=1e-8)
        # aspect
        values = 'min=0\nmax=360\nmean=212.026580596575'
        self.assertRasterFitsUnivar(raster=self.aspect, reference=values, precision=1e-8)
        # pcurvature
        values = 'min=-0.0507194809615612\nmax=0.0395903363823891\nmean=0.00013527328666273'
        self.assertRasterFitsUnivar(raster=self.pcurvature, reference=values, precision=1e-8)
        # tcurvature
        values = 'min=-0.0455724261701107\nmax=0.0380486063659191\nmean=-0.000136686790876467'
        self.assertRasterFitsUnivar(raster=self.tcurvature, reference=values, precision=1e-8)
        # mcurvature
        values = 'min=-0.0437114611268044\nmax=0.032054178416729\nmean=-6.78450785489373e-07'
        self.assertRasterFitsUnivar(raster=self.mcurvature, reference=values, precision=1e-8)
        # deviations
        values = 'min=-0.035444\nmax=0.048801\nmean=4.21945e-05'
        self.assertVectorFitsUnivar(map=self.deviations, column='flt1', reference=values, precision=1e-8)
        # treeseg
        topology = dict(primitives=256)
        self.assertVectorFitsTopoInfo(vector=self.treeseg, reference=topology)
        # overwin
        topology = dict(primitives=256)
        self.assertVectorFitsTopoInfo(vector=self.overwin, reference=topology)

        # test 3D versus attribute
        self.vsurfrst.outputs.elevation = self.elevation_attrib
        self.vsurfrst.inputs.column = 'value'
        self.assertModule(self.vsurfrst)
        self.assertRastersNoDifference(self.elevation, self.elevation_attrib, precision=1e-8)

if __name__ == '__main__':
    test()
