# -*- coding: utf-8 -*-
import os
import io
from collections import OrderedDict

import pytest

from boussole.exceptions import SettingsDiscoveryError
from boussole.conf.discovery import Discover
from boussole.conf.json_backend import SettingsBackendJson
from boussole.conf.yaml_backend import SettingsBackendYaml


class DummyTestBackend:
    """
    Dummy backend object just with object attributes required for
    discovering.
    """
    _default_filename = "boussole.dum"
    _kind_name = "dummy"
    _file_extension = "dum"


@pytest.mark.parametrize("backends,expected_engines,expected_exts,expected_filenames", [
    (
        [],
        (),
        (),
        (),
    ),
    (
        [DummyTestBackend],
        (
            (DummyTestBackend._kind_name, DummyTestBackend),
        ),
        (
            (DummyTestBackend._default_filename, DummyTestBackend._kind_name),
        ),
        (
            (DummyTestBackend._file_extension, DummyTestBackend._kind_name),
        ),
    ),
    (
        [SettingsBackendJson, SettingsBackendYaml, DummyTestBackend],
        (
            (SettingsBackendJson._kind_name, SettingsBackendJson),
            (SettingsBackendYaml._kind_name, SettingsBackendYaml),
            (DummyTestBackend._kind_name, DummyTestBackend),
        ),
        (
            (SettingsBackendJson._default_filename, SettingsBackendJson._kind_name),
            (SettingsBackendYaml._default_filename, SettingsBackendYaml._kind_name),
            (DummyTestBackend._default_filename, DummyTestBackend._kind_name),
        ),
        (
            (SettingsBackendJson._file_extension, SettingsBackendJson._kind_name),
            (SettingsBackendYaml._file_extension, SettingsBackendYaml._kind_name),
            (DummyTestBackend._file_extension, DummyTestBackend._kind_name),
        ),
    ),
])
def test_discover_scan_backends(backends, expected_engines, expected_exts,
                                expected_filenames):
    """
    Discover init engines from default backends
    """
    disco = Discover()

    engines, filenames, extensions = disco.scan_backends(backends)

    assert engines == OrderedDict(expected_engines)
    assert filenames == OrderedDict(expected_exts)
    assert extensions == OrderedDict(expected_filenames)


@pytest.mark.parametrize("filepath,kind,name", [
    ("foo.json", None, "json"),
    ("foo.yml", None, "yaml"),
    ("/home/foo.json", None, "json"),
    ("/home/json/foo.yml", None, "yaml"),
    (".foo", "json", "json"),
    (".foo", "yaml", "yaml"),
    ("/home/bar/.foo", "yaml", "yaml"),
    ("foo.bar", "yaml", "yaml"),
    ("foo.json", "yaml", "yaml"),
])
def test_get_backend_success(filepath, kind, name):
    """
    Discover backend from given filename and kind
    """
    disco = Discover([SettingsBackendJson, SettingsBackendYaml])
    backend = disco.get_engine(filepath, kind=kind)

    assert backend._kind_name == name


@pytest.mark.parametrize("filepath,kind", [
    (".foo", None),
    ("foo.bar", None),
    ("foo.json.bar", None),
    ("/home/bar/.foo", None),
    ("foo.json", "wrong"),
])
def test_get_backend_fail(filepath, kind):
    """
    Error on discovering backend from given filename
    """
    disco = Discover([SettingsBackendJson, SettingsBackendYaml])

    with pytest.raises(SettingsDiscoveryError):
        disco.get_engine(filepath, kind=kind)


def test_search_empty():
    """
    Error if basedir and filepath are empty
    """