"""
    :codeauthor: Nicole Thomas <nicole@saltstack.com>
"""

import logging
import os

import pytest  # pylint: disable=unused-import
import salt.exceptions
import salt.state
import salt.utils.files
import salt.utils.platform

log = logging.getLogger(__name__)


@pytest.fixture
def root_dir(tmp_path):
    return str(tmp_path / "root_dir")


@pytest.fixture
def base_state_tree_dir(root_dir):
    return os.path.join(root_dir, "base_state_tree")


@pytest.fixture
def other_state_tree_dir(root_dir):
    return os.path.join(root_dir, "other_state_tree")


@pytest.fixture
def cache_dir(root_dir):
    return os.path.join(root_dir, "cachedir")


@pytest.fixture
def highstate(
    temp_salt_minion,
    temp_salt_master,
    root_dir,
    base_state_tree_dir,
    other_state_tree_dir,
    cache_dir,
):
    for dpath in (
        root_dir,
        base_state_tree_dir,
        other_state_tree_dir,
        cache_dir,
    ):
        if not os.path.isdir(dpath):
            os.makedirs(dpath)

    test_sls = """
    test state:
      test.succeed_without_changes:
        - name: test
        """

    with pytest.helpers.temp_file("test.sls", test_sls, other_state_tree_dir):

        opts = temp_salt_minion.config.copy()
        opts["root_dir"] = root_dir
        opts["state_events"] = False
        opts["id"] = "match"
        opts["file_client"] = "local"
        opts["file_roots"] = dict(
            base=[base_state_tree_dir], other=[other_state_tree_dir]
        )
        opts["cachedir"] = cache_dir
        opts["test"] = False

        opts.update(
            {
                "transport": "zeromq",
                "auth_tries": 1,
                "auth_timeout": 5,
                "master_ip": "127.0.0.1",
                "master_port": temp_salt_master.config["ret_port"],
                "master_uri": "tcp://127.0.0.1:{}".format(
                    temp_salt_master.config["ret_port"]
                ),
            }
        )

        _highstate = salt.state.HighState(opts)
        _highstate.push_active()

        yield _highstate


def test_lazy_avail_states_base(highstate, base_state_tree_dir, tmp_path):
    top_sls = """
    base:
      '*':
        - core
        """

    core_state = """
    {}/testfile:
      file:
        - managed
        - source: salt://testfile
        - makedirs: true
        """.format(
        str(tmp_path)
    )

    with pytest.helpers.temp_file(
        "top.sls", top_sls, base_state_tree_dir
    ), pytest.helpers.temp_file("core.sls", core_state, base_state_tree_dir):
        # list_states not called yet
        assert not highstate.avail._filled
        assert highstate.avail._avail == {"base": None}
        # After getting 'base' env available states
        highstate.avail["base"]  # pylint: disable=pointless-statement
        assert not highstate.avail._filled
        assert highstate.avail._avail == {"base": ["core", "top"]}


def test_lazy_avail_states_other(highstate, base_state_tree_dir, tmp_path):
    top_sls = """
    base:
      '*':
        - core
        """

    core_state = """
    {}/testfile:
      file:
        - managed
        - source: salt://testfile
        - makedirs: true
        """.format(
        str(tmp_path)
    )

    with pytest.helpers.temp_file(
        "top.sls", top_sls, base_state_tree_dir
    ), pytest.helpers.temp_file("core.sls", core_state, base_state_tree_dir):
        # list_states not called yet
        assert not highstate.avail._filled
        assert highstate.avail._avail == {"base": None}
        # After getting 'other' env available states
        highstate.avail["other"]  # pylint: disable=pointless-statement
        assert highstate.avail._filled
        assert highstate.avail._avail == {"base": None, "other": ["test"]}


def test_lazy_avail_states_multi(highstate, base_state_tree_dir, tmp_path):
    top_sls = """
    base:
      '*':
        - core
        """

    core_state = """
    {}/testfile:
      file:
        - managed
        - source: salt://testfile
        - makedirs: true
        """.format(
        str(tmp_path)
    )

    with pytest.helpers.temp_file(
        "top.sls", top_sls, base_state_tree_dir
    ), pytest.helpers.temp_file("core.sls", core_state, base_state_tree_dir):
        # list_states not called yet
        assert not highstate.avail._filled
        assert highstate.avail._avail == {"base": None}
        # After getting 'base' env available states
        highstate.avail["base"]  # pylint: disable=pointless-statement
        assert not highstate.avail._filled
        assert highstate.avail._avail == {"base": ["core", "top"]}
        # After getting 'other' env available states
        highstate.avail["other"]  # pylint: disable=pointless-statement
        assert highstate.avail._filled
        assert highstate.avail._avail == {"base": ["core", "top"], "other": ["test"]}
