#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# 'License'); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#


#pylint: disable=wildcard-import,missing-docstring,too-many-public-methods

import unittest, json
from qpid_dispatch_internal.management.schema import Schema, BooleanType, EnumType, AttributeType, ValidationError, EnumValue, EntityType
from qpid_dispatch_internal.compat import OrderedDict
import collections

def replace_od(thing):
    """Replace OrderedDict with dict"""
    if isinstance(thing, OrderedDict):
        return dict((k, replace_od(v)) for k,v in thing.iteritems())
    if isinstance(thing, list):
        return [replace_od(t) for t in thing]
    return thing

SCHEMA_1 = {
    "prefix":"org.example",
    "annotations": {
        "entityId": {
            "attributes": {
                "name": {"type":"string", "required": True, "unique":True},
                "type": {"type":"string", "required": True}
            }
        }
    },
    "entityTypes": {
        "container": {
            "singleton": True,
            "annotations" : ["entityId"],
            "attributes": {
                "workerThreads" : {"type":"integer", "default": 1}
            }
        },
        "listener": {
            "annotations" : ["entityId"],
            "attributes": {
                "addr" : {"type":"string"}
            }
        },
        "connector": {
            "annotations" : ["entityId"],
            "attributes": {
                "addr" : {"type":"string"}
            }
        }
    }
}

class SchemaTest(unittest.TestCase):

    def test_bool(self):
        b = BooleanType()
        self.assertTrue(b.validate('on'))
        self.assertTrue(b.validate(True))
        self.assertFalse(b.validate(False))
        self.assertFalse(b.validate('no'))
        self.assertRaises(ValidationError, b.validate, 'x')

    def test_enum(self):
        e = EnumType(['a', 'b', 'c'])
        self.assertEqual(e.validate('a'), 'a')
        self.assertEqual(e.validate(1), 'b')
        self.assertEqual(e.validate('c'), 2)
        self.assertEqual(e.validate(2), 2)
        self.assertRaises(ValidationError, e.validate, 'foo')
        self.assertRaises(ValidationError, e.validate, 3)

        self.assertEqual('["x"]', json.dumps([EnumValue('x',3)]))

    def test_attribute_def(self):
        a = AttributeType('foo', 'string', default='FOO')
        self.assertEqual('FOO', a.missing_value())
        self.assertEqual(a.validate('x'), 'x')

        a = AttributeType('foo', 'string', default='FOO', required=True)
        self.assertEqual('FOO', a.missing_value())

        a = AttributeType('foo', 'string', required=True)
        self.assertRaises(ValidationError, a.missing_value) # Missing required value.

        a = AttributeType('foo', 'string', value='FOO') # Fixed value
        self.assertEqual('FOO', a.missing_value())
        self.assertEqual(a.validate('FOO'), 'FOO')
        self.assertRaises(ValidationError, a.validate, 'XXX') # Bad fixed value

        self.assertRaises(ValidationError, AttributeType, 'foo', 'string', value='FOO', default='BAR') # Illegal

        a = AttributeType('foo', 'integer')
        self.assertEqual(3, a.validate(3))
        self.assertEqual(3, a.validate('3'))
        self.assertEqual(3, a.validate(3.0))
        self.assertRaises(ValidationError, a.validate, None)
        self.assertRaises(ValidationError, a.validate, "xxx")


    def test_entity_type(self):
        s = Schema(annotations={
            'i1':{'attributes': { 'foo1': {'type':'string', 'default':'FOO1'}}},
            'i2':{'attributes': { 'foo2': {'type':'string', 'default':'FOO2'}}}})

        e = EntityType('MyEntity', s, attributes={
            'foo': {'type':'string', 'default':'FOO'},
            'req': {'type':'integer', 'required':True},
            'e': {'type':['x', 'y']}})
        e.init()
        self.assertRaises(ValidationError, e.validate, {}) # Missing required 'req'
        self.assertEqual(e.validate({'req':42}), {'foo': 'FOO', 'req': 42})
        # Try with an annotation
        e = EntityType('e2', s, attributes={'x':{'type':'integer'}}, annotations=['i1', 'i2'])
        e.init()
        self.assertEqual(e.validate({'x':1}), {'x':1, 'foo1': 'FOO1', 'foo2': 'FOO2'})

    def test_entity_refs(self):
        e = EntityType('MyEntity', Schema(), attributes={
            'type': {'type': 'string', 'required': True, 'value': '$$entityType'},
            'name': {'type':'string', 'default':'$identity'},
            'identity': {'type':'string', 'default':'$name', "required": True}})

        self.assertEqual({'type': 'MyEntity', 'identity': 'x', 'name': 'x'},
                         e.validate({'identity':'x'}))
        self.assertEqual({'type': 'MyEntity', 'identity': 'x', 'name': 'x'},
                         e.validate({'name':'x'}))
        self.assertEqual({'type': 'MyEntity', 'identity': 'x', 'name': 'y'},
                         e.validate({'identity': 'x', 'name':'y'}))
        self.assertRaises(ValidationError, e.validate, {}) # Circular reference.

    def test_entity_annotation_refs(self):
        s = Schema(annotations={
            'i1': {'attributes': {
                'name': {'type':'string', 'default':'$identity'},
                'identity': {'type':'string', 'default':'$name', "required": True}}}})

        e = EntityType('MyEntity', s, attributes={}, annotations=['i1'])
        e.init()
        self.assertEqual({'identity': 'x', 'name': 'x'}, e.validate({'identity':'x'}))
        self.assertEqual({'identity': 'x', 'name': 'x'}, e.validate({'name':'x'}))
        self.assertEqual({'identity': 'x', 'name': 'y'}, e.validate({'identity': 'x', 'name':'y'}))
        self.assertRaises(ValidationError, e.validate, {})

    def test_schema_validate(self):
        s = Schema(**SCHEMA_1)
        # Duplicate unique attribute 'name'
        m = [{'type': 'listener', 'name':'x'},
             {'type': 'listener', 'name':'x'}]
        self.assertRaises(ValidationError, s.validate_all, m)
        # Duplicate singleton entity 'container'
        m = [{'type': 'container', 'name':'x'},
             {'type': 'container', 'name':'y'}]
        self.assertRaises(ValidationError, s.validate_all, m)
        # Valid model
        m = [{'type': 'container', 'name':'x'},
             {'type': 'listener', 'name':'y'}]
        s.validate_all(m)

    def test_schema_entity(self):
        s = Schema(**SCHEMA_1)
        self.assertRaises(ValidationError, s.entity, {'type': 'nosuch'})
        self.assertRaises(ValidationError, s.entity, {'type': 'listener', 'nosuch': 'x'})
        e = s.entity({'type': 'listener', 'name':'x', 'addr':'foo'})
        self.assertEqual(e.attributes, {'type': 'org.example.listener', 'name':'x', 'addr':'foo'})
        self.assertEqual(e['addr'], 'foo')
        self.assertRaises(ValidationError, e.__setitem__, 'nosuch', 'x')
        try:
            e.nosuch = 'x'
            self.fail("Expected exception")
        except: pass

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