"""Test filter and schema validators"""

from unittest import TestCase
from voluptuous import Schema
from es_client.exceptions import FailedValidation
from es_client.schemacheck import SchemaCheck
from curator.exceptions import ConfigurationError
from curator.validators.filter_functions import validfilters, singlefilter


def shared_result(config, action):
    """Test functions should be able to reuse this"""
    return SchemaCheck(
        config, Schema(validfilters(action)), 'filters', 'testing'
    ).result()


class TestFilters(TestCase):
    def test_single_raises_configuration_error(self):
        data = {'max_num_segments': 1, 'exclude': True}
        self.assertRaises(ConfigurationError, singlefilter, 'forcemerge', data)


class TestFilterTypes(TestCase):
    def test_alias(self):
        action = 'delete_indices'
        config = [
            {
                'filtertype': 'alias',
                'aliases': ['alias1', 'alias2'],
                'exclude': False,
            }
        ]
        self.assertEqual(config, shared_result(config, action))

    def test_age(self):
        action = 'delete_indices'
        config = [
            {
                'filtertype': 'age',
                'direction': 'older',
                'unit': 'days',
                'unit_count': 1,
                'source': 'field_stats',
                'field': '@timestamp',
            }
        ]
        self.assertEqual(config, shared_result(config, action))

    def test_age_with_string_unit_count(self):
        action = 'delete_indices'
        config = [
            {
                'filtertype': 'age',
                'direction': 'older',
                'unit': 'days',
                'unit_count': "1",
                'source': 'field_stats',
                'field': '@timestamp',
            }
        ]
        result = shared_result(config, action)
        self.assertEqual(1, result[0]['unit_count'])

    def test_allocated(self):
        action = 'delete_indices'
        config = [
            {
                'filtertype': 'allocated',
                'key': 'foo',
                'value': 'bar',
                'allocation_type': 'require',
                'exclude': False,
            }
        ]
        self.assertEqual(config, shared_result(config, action))

    def test_closed(self):
        action = 'delete_indices'
        config = [
            {
                'filtertype': 'closed',
                'exclude': False,
            }
        ]
        self.assertEqual(config, shared_result(config, action))

    def test_count(self):
        action = 'delete_indices'
        config = [
            {
                'filtertype': 'count',
                'count': 1,
                'reverse': True,
                'exclude': False,
            }
        ]
        self.assertEqual(config, shared_result(config, action))

    def test_forcemerged(self):
        action = 'delete_indices'
        config = [
            {
                'filtertype': 'forcemerged',
                'max_num_segments': 1,
                'exclude': False,
            }
        ]
        self.assertEqual(config, shared_result(config, action))

    def test_kibana(self):
        action = 'delete_indices'
        config = [
            {
                'filtertype': 'kibana',
                'exclude': False,
            }
        ]
        self.assertEqual(config, shared_result(config, action))

    def test_opened(self):
        action = 'delete_indices'
        config = [
            {
                'filtertype': 'opened',
                'exclude': False,
            }
        ]
        self.assertEqual(config, shared_result(config, action))

    def test_space_name_age(self):
        action = 'delete_indices'
        config = [
            {
                'filtertype': 'space',
                'disk_space': 1,
                'use_age': True,
                'exclude': False,
                'source': 'name',
                'timestring': '%Y.%m.%d',
            }
        ]
        self.assertEqual(config, shared_result(config, action))

    def test_space_name_age_string_float(self):
        action = 'delete_indices'
        config = [
            {
                'filtertype': 'space',
                'disk_space': "1.0",
                'use_age': True,
                'exclude': False,
                'source': 'name',
                'timestring': '%Y.%m.%d',
            }
        ]
        result = shared_result(config, action)
        self.assertEqual(1.0, result[0]['disk_space'])

    def test_space_name_age_no_ts(self):
        action = 'delete_indices'
        config = [
            {
                'filtertype': 'space',
                'disk_space': 1,
                'use_age': True,
                'exclude': False,
                'source': 'name',
            }
        ]
        schema = SchemaCheck(config, Schema(validfilters(action)), 'filters', 'testing')
        self.assertRaises(FailedValidation, schema.result)

    def test_space_field_stats_age(self):
        action = 'delete_indices'
        config = [
            {
                'filtertype': 'space',
                'disk_space': 1,
                'use_age': True,
                'exclude': False,
                'source': 'field_stats',
                'field': '@timestamp',
            }
        ]
        self.assertEqual(config, shared_result(config, action))

    def test_space_field_stats_age_no_field(self):
        action = 'delete_indices'
        config = [
            {
                'filtertype': 'space',
                'disk_space': 1,
                'use_age': True,
                'exclude': False,
                'source': 'field_stats',
            }
        ]
        schema = SchemaCheck(config, Schema(validfilters(action)), 'filters', 'testing')
        self.assertRaises(FailedValidation, schema.result)

    def test_space_creation_date_age(self):
        action = 'delete_indices'
        config = [
            {
                'filtertype': 'space',
                'disk_space': 1,
                'use_age': True,
                'exclude': False,
                'source': 'creation_date',
            }
        ]
        self.assertEqual(config, shared_result(config, action))

    def test_state(self):
        action = 'delete_snapshots'
        config = [
            {
                'filtertype': 'state',
                'state': 'SUCCESS',
                'exclude': False,
            }
        ]
        self.assertEqual(config, shared_result(config, action))

    def test_shards(self):
        action = 'shrink'
        config = [
            {
                'filtertype': 'shards',
                'number_of_shards': 5,
                'shard_filter_behavior': 'greater_than',
                'exclude': False,
            }
        ]
        self.assertEqual(config, shared_result(config, action))
