import pytest
import calculate.vars.main.os as main_os
import calculate.vars.main.cl as main_cl
import calculate.vars.main.os.x11 as main_os_x11
from calculate.vars.main.cl import CmdlineParams
import calculate.vars.install.os.func as install_os
import mock
from itertools import chain


class Var:
    def __init__(self, value):
        self.value = value


@pytest.mark.parametrize(
    'case',
    [
        {
            "name": "failed xdpyinfo",
            "failed": True,
            "data": "",
            "result": ""
        }, {
            "name": "worked xdpyinfo",
            "failed": False,
            "data": open('tests/vars/xdpyinfo.output', 'r').read(),
            "result": "1920x1080"
        },
        {
            "name": "xdpyinfo not dimenstions info",
            "failed": False,
            "data": "some trash\ninfo",
            "result": ""
        },
    ],
    ids=lambda x: x["name"])
@pytest.mark.calculate_vars
def test_main_os_x11_resolution(case):
    with mock.patch('calculate.vars.main.os.x11.Process.failed') as failed:
        with mock.patch('calculate.vars.main.os.x11.Process.read_lines'
                        ) as read_lines:
            failed.return_value = case["failed"]
            read_lines.return_value = case["data"].split("\n")
            assert main_os_x11.get_resolution_by_xdpyinfo() == case["result"]


empty_calculate_cmdhash = {
    CmdlineParams.Locale: "",
    CmdlineParams.Keymap: "",
    CmdlineParams.Timezone: "",
    CmdlineParams.Resolution: "",
    CmdlineParams.Video: "",
    CmdlineParams.Composite: "",
    CmdlineParams.Domain: "",
    CmdlineParams.DomainPassword: "",
    CmdlineParams.Audio: "",
    CmdlineParams.Clock: ""
}


def concat_dict(d1, **d2):
    return {x: y for x, y in chain(d1.items(), d2.items())}


@pytest.mark.parametrize(
    'case',
    [
        {
            "name": "empty cmdline",
            "data": "",
            "result": empty_calculate_cmdhash,
        },
        {
            "name": "cmd has not calculate param",
            "data": "BOOT_IMAGE=(loop)/boot/vmlinuz root=live iso-scan/filename=/linux/cld-20201120-x86_64.iso quiet verbose docache",
            "result": empty_calculate_cmdhash,
        },
        {
            "name": "cmd has wrong calculate param",
            "data": "BOOT_IMAGE=(loop)/boot/vmlinuz root=live iso-scan/filename=/linux/cld-20201120-x86_64.iso quiet verbose calculate=testingvalue docache",
            "result": empty_calculate_cmdhash,
        },
        {
            "name": "cmd has wrong calculate param name",
            "data": "BOOT_IMAGE=(loop)/boot/vmlinuz root=live iso-scan/filename=/linux/cld-20201120-x86_64.iso quiet verbose calculate=testing:value docache",
            "result": empty_calculate_cmdhash,
        },
        {
            "name": "cmd has only video",
            "data": "BOOT_IMAGE=(loop)/boot/vmlinuz root=live iso-scan/filename=/linux/cld-20201120-x86_64.iso quiet verbose calculate=video:nvidia docache",
            "result": concat_dict(empty_calculate_cmdhash, video="nvidia")
        },
        {
            "name": "cmd has only video and resolution",
            "data": "BOOT_IMAGE=(loop)/boot/vmlinuz root=live iso-scan/filename=/linux/cld-20201120-x86_64.iso quiet verbose calculate=video:nvidia,resolution:1920x1080 docache",
            "result": concat_dict(empty_calculate_cmdhash, video="nvidia", resolution="1920x1080")
        },
    ],
    ids=lambda x: x["name"])
@pytest.mark.calculate_vars
def test_main_cl_cmdline(case):
    with mock.patch('calculate.vars.main.cl.readFile') as readFile:
        readFile.return_value = case["data"]
        assert main_cl.get_calculate_cmdline() == case["result"]


@pytest.mark.parametrize(
    'case',
    [
        {
            "source": "i686",
            "result": "x86"
        },
        {
            "source": "i386",
            "result": "x86"
        },
        {
            "source": "x86_64",
            "result": "amd64"
        },
    ],
    ids=lambda x: "{}->{}".format(x["source"], x["result"]))
@pytest.mark.calculate_vars
def test_main_os_get_arch_gentoo(case):
    assert main_os.get_arch_gentoo(Var(case["source"])) == case["result"]


@pytest.mark.parametrize(
    'case',
    [
        {
            "name": "pulseaudio exists",
            "exists": True,
            "result": ["alsa", "pulseaudio"]
        },
        {
            "name": "pulseaudio not exists",
            "exists": False,
            "result": ["alsa"]
        },
    ],
    ids=lambda x: x["name"])
@pytest.mark.calculate_vars
def test_install_os_get_available_audio_system(case):
    with mock.patch('calculate.vars.install.os.func.'
                    'PackageAtomParser.is_package_exists') as exists:
        exists.return_value = case["exists"]
        assert install_os.get_available_audio_system() == case["result"]


@pytest.mark.parametrize(
    'case',
    [
        {
            "name": "default all available",
            "available_systems": ["alsa", "pulseaudio"],
            "cmdline_audio": "",
            "result": "pulseaudio"
        },
        {
            "name": "default all pulse unavailable",
            "available_systems": ["alsa"],
            "cmdline_audio": "",
            "result": "alsa"
        },
        {
            "name": "all available alsa selected",
            "available_systems": ["alsa", "pulseaudio"],
            "cmdline_audio": "alsa",
            "result": "alsa"
        },
        {
            "name": "all available pulse selected",
            "available_systems": ["alsa", "pulseaudio"],
            "cmdline_audio": "pulseaudio",
            "result": "pulseaudio"
        },
        {
            "name": "all available wrong cmd line",
            "available_systems": ["alsa", "pulseaudio"],
            "cmdline_audio": "wrong",
            "result": "pulseaudio"
        },
        {
            "name": "pulse not available wrong cmd line",
            "available_systems": ["alsa"],
            "cmdline_audio": "wrong",
            "result": "alsa"
        },
    ],
    ids=lambda x: x["name"])
@pytest.mark.calculate_vars
def test_install_os_get_available_audio_system_other(case):
    assert install_os.get_audio_selected(
        Var(case["available_systems"]),
        Var(case["cmdline_audio"])) == case["result"]
