import os
import unittest
from typing import Dict

from spectator import Config


class ConfigTest(unittest.TestCase):

    @staticmethod
    def all_expected_tags() -> Dict[str, str]:
        return {
            "nf.container": "main",
            "nf.process": "python",
        }

    @staticmethod
    def setup_environment() -> None:
        os.environ["NETFLIX_PROCESS_NAME"] = "python"
        os.environ["TITUS_CONTAINER_NAME"] = "main"

    @staticmethod
    def clear_environment() -> None:
        keys = ["NETFLIX_PROCESS_NAME", "SPECTATOR_OUTPUT_LOCATION", "TITUS_CONTAINER_NAME"]

        for key in keys:
            try:
                del os.environ[key]
            except KeyError:
                pass

    @staticmethod
    def get_location(location: str) -> str:
        return Config(location).location

    def test_is_valid_output_location(self):
        config = Config()
        self.assertTrue(config.is_valid_output_location("none"))
        self.assertTrue(config.is_valid_output_location("memory"))
        self.assertTrue(config.is_valid_output_location("stdout"))
        self.assertTrue(config.is_valid_output_location("stderr"))
        self.assertTrue(config.is_valid_output_location("udp"))
        self.assertTrue(config.is_valid_output_location("unix"))
        self.assertTrue(config.is_valid_output_location("file://testfile.txt"))
        self.assertTrue(config.is_valid_output_location("udp://localhost:1234"))
        self.assertTrue(config.is_valid_output_location("unix:///tmp/socket.sock"))
        self.assertFalse(config.is_valid_output_location("invalid"))

    def test_default_config(self):
        self.setup_environment()
        config = Config()
        self.assertEqual(self.all_expected_tags(), config.extra_common_tags)
        self.assertEqual("udp", config.location)
        self.clear_environment()

    def test_env_location_override(self):
        os.environ["SPECTATOR_OUTPUT_LOCATION"] = "memory"
        config = Config()
        self.assertEqual("memory", config.location)
        self.clear_environment()

    def test_invalid_env_location_override(self):
        os.environ["SPECTATOR_OUTPUT_LOCATION"] = "invalid"
        self.assertRaises(ValueError, Config)
        self.clear_environment()

    def test_extra_common_tags(self):
        self.setup_environment()
        config = Config(extra_common_tags={"extra-tag": "foo"})
        self.assertEqual("udp", config.location)
        self.assertEqual({"extra-tag": "foo", "nf.container": "main", "nf.process": "python"}, config.extra_common_tags)
        self.clear_environment()

    def test_valid_output_locations(self):
        self.assertEqual("none", self.get_location("none"))
        self.assertEqual("memory", self.get_location("memory"))
        self.assertEqual("stderr", self.get_location("stderr"))
        self.assertEqual("stdout", self.get_location("stdout"))
        self.assertEqual("udp", self.get_location("udp"))
        self.assertEqual("unix", self.get_location("unix"))
        self.assertEqual("file://", self.get_location("file://"))
        self.assertEqual("udp://", self.get_location("udp://"))

    def test_invalid_output_locations(self):
        self.assertRaises(ValueError, self.get_location, None)
        self.assertRaises(ValueError, self.get_location, "foo")
