# Copyright iris-grib contributors
#
# This file is part of iris-grib and is released under the LGPL license.
# See COPYING and COPYING.LESSER in the root of the repository for full
# licensing details.
"""
Test function
:func:`iris_grib._load_convert.grid_definition_template_4_and_5`.

"""

# import iris_grib.tests first so that some things can be initialised
# before importing anything else.
import iris_grib.tests as tests

from copy import deepcopy
from unittest import mock
import warnings

from iris.coords import DimCoord
import numpy as np

from iris_grib._load_convert import (grid_definition_template_4_and_5,
                                     _MDI as MDI)


RESOLUTION = 1e6


class Test(tests.IrisGribTest):
    def setUp(self):
        self.patch('warnings.warn')
        self.patch('iris_grib._load_convert._is_circular', return_value=False)
        self.metadata = {'factories': [], 'references': [],
                         'standard_name': None,
                         'long_name': None, 'units': None, 'attributes': {},
                         'cell_methods': [], 'dim_coords_and_dims': [],
                         'aux_coords_and_dims': []}
        self.cs = mock.sentinel.coord_system
        self.data = np.arange(10, dtype=np.float64)

    def _check(self, section, request_warning,
               expect_warning=False, y_dim=0, x_dim=1):
        this = 'iris_grib._load_convert.options'
        with mock.patch(this, warn_on_unsupported=request_warning):
            metadata = deepcopy(self.metadata)
            # The called being tested.
            grid_definition_template_4_and_5(section, metadata,
                                             'latitude', 'longitude', self.cs)
            expected = deepcopy(self.metadata)
            coord = DimCoord(self.data,
                             standard_name='latitude',
                             units='degrees',
                             coord_system=self.cs)
            expected['dim_coords_and_dims'].append((coord, y_dim))
            coord = DimCoord(self.data,
                             standard_name='longitude',
                             units='degrees',
                             coord_system=self.cs)
            expected['dim_coords_and_dims'].append((coord, x_dim))
            self.assertEqual(metadata, expected)
            if expect_warning:
                self.assertEqual(len(warnings.warn.mock_calls), 1)
                args, kwargs = warnings.warn.call_args
                self.assertIn('resolution and component flags', args[0])
            else:
                self.assertEqual(len(warnings.warn.mock_calls), 0)

    def test_resolution_default_0(self):
        for request_warn in [False, True]:
            section = {'basicAngleOfTheInitialProductionDomain': 0,
                       'subdivisionsOfBasicAngle': 0,
                       'resolutionAndComponentFlags': 0,
                       'longitudes': self.data * RESOLUTION,
                       'latitudes': self.data * RESOLUTION,
                       'scanningMode': 0}
            self._check(section, request_warn)

    def test_resolution_default_mdi(self):
        for request_warn in [False, True]:
            section = {'basicAngleOfTheInitialProductionDomain': MDI,
                       'subdivisionsOfBasicAngle': MDI,
                       'resolutionAndComponentFlags': 0,
                       'longitudes': self.data * RESOLUTION,
                       'latitudes': self.data * RESOLUTION,
                       'scanningMode': 0}
            self._check(section, request_warn)

    def test_resolution(self):
        angle = 10
        for request_warn in [False, True]:
            section = {'basicAngleOfTheInitialProductionDomain': 1,
                       'subdivisionsOfBasicAngle': angle,
                       'resolutionAndComponentFlags': 0,
                       'longitudes': self.data * angle,
                       'latitudes': self.data * angle,
                       'scanningMode': 0}
            self._check(section, request_warn)

    def test_uv_resolved_warn(self):
        angle = 100
        for warn in [False, True]:
            section = {'basicAngleOfTheInitialProductionDomain': 1,
                       'subdivisionsOfBasicAngle': angle,
                       'resolutionAndComponentFlags': 0x08,
                       'longitudes': self.data * angle,
                       'latitudes': self.data * angle,
                       'scanningMode': 0}
            self._check(section, warn, expect_warning=warn)

    def test_j_consecutive(self):
        angle = 1000
        for request_warn in [False, True]:
            section = {'basicAngleOfTheInitialProductionDomain': 1,
                       'subdivisionsOfBasicAngle': angle,
                       'resolutionAndComponentFlags': 0,
                       'longitudes': self.data * angle,
                       'latitudes': self.data * angle,
                       'scanningMode': 0x20}
            self._check(section, request_warn, y_dim=1, x_dim=0)


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