import glob
import json
import os
import re

from lxml import etree
import pytest

import inventory_provider

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


class MockedRedis(object):

    db = None

    def __init__(self, *args, **kwargs):
        if MockedRedis.db is None:
            test_data_filename = os.path.join(
                TEST_DATA_DIRNAME,
                "router-info.json")
            with open(test_data_filename) as f:
                MockedRedis.db = json.loads(f.read())

    def set(self, name, value):
        MockedRedis.db[name] = value

    def get(self, name):
        value = MockedRedis.db.get(name, None)
        if value is None:
            return None
        return value.encode('utf-8')

    def keys(self, glob=None):
        if not glob:
            return list([k.encode("utf-8") for k in MockedRedis.db.keys()])
        m = re.match(r'^([^*]+)\*$', glob)
        assert m  # all expected global are like this
        return list([
            k.encode("utf-8") for k in MockedRedis.db.keys()
            if k.startswith(m.group(1))])

    def delete(self, key):
        if isinstance(key, bytes):
            key = key.decode('utf-8')
        del MockedRedis.db[key]


@pytest.fixture
def classifier_cache_test_entries():
    filename = os.path.join(
        TEST_DATA_DIRNAME, 'classifier-cache-entries.json')
    with open(filename) as f:
        return json.loads(f.read())


@pytest.fixture
def mocked_redis(mocker):
    mocker.patch(
        'inventory_provider.tasks.common.redis.StrictRedis',
        MockedRedis)
    return MockedRedis()


def pytest_generate_tests(metafunc):

    def _junosspace_hosts():
        filename = os.path.join(TEST_DATA_DIRNAME, "junosspace-devices.xml")
        with open(filename) as f:
            doc = etree.fromstring(f.read().encode('utf-8'))
            for name in doc.xpath('//devices/device/name/text()'):
                m = re.match(r'^(mx[12].*)\.re0', name)
                if m:
                    yield m.group(1) + '.geant.net'

    # TODO: can we really not get netconf data for all routers?
    def _available_netconf_hosts():
        for fn in glob.glob(os.path.join(TEST_DATA_DIRNAME, '*-netconf.xml')):
            m = re.match('(.*)-netconf.xml', os.path.basename(fn))
            assert m  # sanity
            yield m.group(1)

    routers = list(set(_junosspace_hosts()) & set(_available_netconf_hosts()))
    metafunc.parametrize("router", routers)