from __future__ import annotations

from typing import TYPE_CHECKING, List

from cyst.api.environment.configuration import ExploitConfiguration
from cyst.api.logic.exploit import Exploit, VulnerableService, ExploitLocality, ExploitCategory, ExploitParameter, \
    ExploitParameterType

from cyst.core.environment.stores import ExploitStoreImpl
from cyst.core.logic.exploit import VulnerableServiceImpl, ExploitParameterImpl, ExploitImpl

if TYPE_CHECKING:
    from cyst.core.environment.environment import _Environment


class ExploitConfigurationImpl(ExploitConfiguration):
    def __init__(self, env: _Environment):
        self._env = env

    def create_vulnerable_service(self, id: str, min_version: str = "0.0.0",
                                  max_version: str = "0.0.0") -> VulnerableService:
        return VulnerableServiceImpl(id, min_version, max_version)

    def create_exploit_parameter(self, exploit_type: ExploitParameterType, value: str = "",
                                 immutable: bool = False) -> ExploitParameter:
        return ExploitParameterImpl(exploit_type, value, immutable)

    def create_exploit(self, id: str = "", services: List[VulnerableService] = None, locality: ExploitLocality = ExploitLocality.NONE,
                       category: ExploitCategory = ExploitCategory.NONE,
                       *parameters: ExploitParameter) -> Exploit:
        return ExploitImpl(id, services, locality, category, *parameters)

    def add_exploit(self, *exploits: Exploit) -> None:
        _add_exploit(self._env, *exploits)

    def clear_exploits(self) -> None:
        _clear_exploits(self._env)


# ------------------------------------------------------------------------------------------------------------------
# Exploit configuration
def _add_exploit(self: _Environment, *exploits: Exploit) -> None:
    ExploitStoreImpl.cast_from(self._environment_resources.exploit_store).add_exploit(*exploits)


def _clear_exploits(self: _Environment) -> None:
    ExploitStoreImpl.cast_from(self._environment_resources.exploit_store).clear()
