import json
import os

import jsonschema

from inventory_provider import snmp

import inventory_provider

TEST_DATA_DIRNAME = os.path.realpath(os.path.join(
    inventory_provider.__path__[0],
    "..",
    "test",
    "data"))


def interfaces_walk_responses():
    test_data_filename = os.path.join(
        TEST_DATA_DIRNAME, "snmp-walk-interfaces.json")
    with open(test_data_filename) as f:
        return json.loads(f.read())


def peering_walk_responses():
    test_data_filename = os.path.join(
        TEST_DATA_DIRNAME, "snmp-peer-info.json")
    with open(test_data_filename) as f:
        for peering in json.loads(f.read()):
            yield {'oid': peering['oid'], 'value': 6}


def _gen_mocked_nextCmd(mocked_walk_data):
    engineErrorIndication = 0
    pduErrorIndication = 0
    errorIndex = 0
    varBinds = [[x['oid'], x['value']] for x in mocked_walk_data]

    def _mocked_nextCmd(*args, **kwargs):
        yield engineErrorIndication, pduErrorIndication, errorIndex, varBinds

    return _mocked_nextCmd


def test_snmp_interfaces(mocker):

    expected_result_schema = {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "type": "array",
        "items": {
            "type": "object",
            "properties": {
                "name": {"type": "string"},
                "index": {"type": "integer"}
            },
            "required": ["name", "index"],
            "additionalProperties": False
        }
    }

    test_data = list(interfaces_walk_responses())
    assert test_data  # sanity

    _mocked_nextCmd = _gen_mocked_nextCmd(test_data)
    mocker.patch('inventory_provider.snmp.nextCmd', _mocked_nextCmd)
    mocker.patch('inventory_provider.snmp.UdpTransportTarget', lambda x: None)

    interfaces = list(snmp.get_router_snmp_indexes('ignored', 'ignored'))

    jsonschema.validate(interfaces, expected_result_schema)
    assert len(interfaces) == len(test_data)


def test_peer_info(mocker):

    expected_result_schema = {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "type": "array",
        "items": {
            "type": "object",
            "properties": {
                "local": {"type": "string"},
                "remote": {"type": "string"},
                "oid": {"type": "string"}
            },
            "required": ["local", "remote", "oid"],
            "additionalProperties": False
        }
    }

    test_data = list(peering_walk_responses())
    assert test_data  # sanity

    _mocked_nextCmd = _gen_mocked_nextCmd(test_data)
    mocker.patch('inventory_provider.snmp.nextCmd', _mocked_nextCmd)
    mocker.patch('inventory_provider.snmp.UdpTransportTarget', lambda x: None)

    peerings = list(snmp.get_peer_state_info('ignored', 'ignored'))

    jsonschema.validate(peerings, expected_result_schema)
    assert len(peerings) == len(test_data)