from fmcapi.api_objects.apiclasstemplate import APIClassTemplate
from .accesspolicies import AccessPolicies
from fmcapi.api_objects.device_services.devicerecords import DeviceRecords
from .prefilterpolicies import PreFilterPolicies
import logging
import warnings


class HitCounts(APIClassTemplate):
    """
    The HitCounts Object in the FMC.
    """

    VALID_JSON_DATA = []
    VALID_FOR_KWARGS = VALID_JSON_DATA + [
        "acp_id",
        "acp_name",
        "device_id",
        "device_name",
        "fetchZeroHitcount",
        "limit",
    ]
    PREFIX_URL = "/policy/accesspolicies"
    REQUIRED_FOR_PUT = ["acp_id", "device_id"]
    REQUIRED_FOR_DELETE = ["acp_id", "device_id"]
    REQUIRED_FOR_GET = ["acp_id", "device_id"]
    VALID_CHARACTERS_FOR_NAME = """[.\w\d_\- ]"""
    FIRST_SUPPORTED_FMC_VERSION = "6.4"

    @property
    def URL_SUFFIX(self):
        """
        Add the URL suffixes for filter.
        """
        filter_init = '?filter="'
        filter_string = filter_init

        self.URL = self.URL.split("?")[0]

        if self.device_id:
            filter_string += f"deviceId:{self.device_id};"
        if self.prefilter_ids:
            filter_string += f"ids:{self.prefilter_ids};"
        if self.fetchZeroHitCount:
            filter_string += f"fetchZeroHitCount:{self._fetchZeroHitCount};"

        if filter_string == filter_init:
            filter_string += '"'
        filter_string = f'{filter_string[:-1]}"&expanded=true'

        if "limit" in self.__dict__:
            filter_string += f"&limit={self.limit}"
        return filter_string

    @property
    def fetchZeroHitCount(self):
        return self._fetchZeroHitCount

    @fetchZeroHitCount.setter
    def fetchZeroHitCount(self, value=False):
        self._fetchZeroHitCount = value
        # Rebuild the URL with possible new information
        self.URL = self.URL.split("?")[0]
        self.URL = f"{self.URL}{self.URL_SUFFIX}"

    def __init__(self, fmc, **kwargs):
        logging.debug("In __init__() for HitCounts class.")
        self.device_id = None
        self.prefilter_ids = []
        self.fetchZeroHitCount = False
        super().__init__(fmc, **kwargs)
        self.parse_kwargs(**kwargs)
        self.type = "HitCount"
        self.URL = f"{self.URL}{self.URL_SUFFIX}"

    def parse_kwargs(self, **kwargs):
        super().parse_kwargs(**kwargs)
        logging.debug("In parse_kwargs() for HitCounts class.")
        if "acp_id" in kwargs:
            self.acp(acp_id=kwargs["acp_id"])
        if "acp_name" in kwargs:
            self.acp(name=kwargs["acp_name"])
        if "device_id" in kwargs:
            self.device(id=kwargs["device_id"])
        if "device_name" in kwargs:
            self.device(name=kwargs["device_name"])

    def acp(self, name="", acp_id=""):
        # either name or id of the ACP should be given
        logging.debug("In acp() for HitCounts class.")
        if acp_id != "":
            self.acp_id = acp_id
            self.URL = f"{self.fmc.configuration_url}{self.PREFIX_URL}/{self.acp_id}/operational/hitcounts"
            self.acp_added_to_url = True
        elif name != "":
            acp1 = AccessPolicies(fmc=self.fmc)
            acp1.get(name=name)
            if "id" in acp1.__dict__:
                self.acp_id = acp1.id
                self.URL = f"{self.fmc.configuration_url}{self.PREFIX_URL}/{self.acp_id}/operational/hitcounts"
                self.acp_added_to_url = True
            else:
                logging.warning(
                    f'Access Control Policy "{name}" not found.  Cannot configure acp for HitCounts.'
                )
        else:
            logging.error("No accessPolicy name or id was provided.")
        # Rebuild the URL with possible new information
        self.URL = self.URL.split("?")[0]
        self.URL = f"{self.URL}{self.URL_SUFFIX}"

    def device(self, name="", id=""):
        logging.debug("In device() for HitCounts class")
        if id != "":
            self.device_id = id
        elif name != "":
            device1 = DeviceRecords(fmc=self.fmc)
            device1.get(name=name)
            if "id" in device1.__dict__:
                self.device_id = device1.id
            else:
                logging.warning(
                    f'Device "{name}" not found.  Cannot configure device for HitCounts.'
                )
        else:
            logging.error("No device name or id was provided.")
        # Rebuild the URL with possible new information
        self.URL = self.URL.split("?")[0]
        self.URL = f"{self.URL}{self.URL_SUFFIX}"

    def prefilter_policies(self, action, name="", prefilter_id=""):
        logging.debug("In prefilter_policies_tags() for HitCounts class.")
        if action == "add":
            ppolicy = PreFilterPolicies(fmc=self.fmc)
            if prefilter_id:
                ppolicy.get(id=prefilter_id)
            elif name:
                ppolicy.get(name=name)
            if "id" in ppolicy.__dict__:
                if self.prefilter_ids:
                    duplicate = False
                    for obj in self.prefilter_ids.split(","):
                        if obj == ppolicy.id:
                            duplicate = True
                            logging.warning(
                                f"Id, {ppolicy.id}, already in prefilter_ids not duplicating."
                            )
                            break
                    if not duplicate:
                        self.prefilter_ids.append(ppolicy.id)
                        logging.info(
                            f'Adding "{ppolicy.id}" to prefilter_ids for this HitCounts.'
                        )
                else:
                    self.prefilter_ids.append(ppolicy.id)
                    logging.info(
                        f'Adding "{ppolicy.id}" to prefilter_ids for this HitCounts.'
                    )
            else:
                if name:
                    logging.warning(
                        f'Prefilter, "{name}", not found.  Cannot add to HitCounts.'
                    )
                elif prefilter_id:
                    logging.warning(
                        f"Prefilter, {prefilter_id}, not found.  Cannot add to HitCounts."
                    )
        elif action == "remove":
            ppolicy = PreFilterPolicies(fmc=self.fmc)
            if prefilter_id:
                ppolicy.get(id=prefilter_id)
            elif name:
                ppolicy.get(name=name)
            if "id" in ppolicy.__dict__:
                if self.prefilter_ids:
                    objects = []
                    for obj in self.prefilter_ids:
                        if obj != ppolicy.id:
                            objects.append(obj)
                    self.prefilter_ids = objects
                    logging.info(
                        f'Removed "{ppolicy.id}" from prefilter_ids for this HitCounts.'
                    )
                else:
                    logging.info(
                        "prefilter_ids is empty for this HitCounts.  Nothing to remove."
                    )
            else:
                logging.warning(
                    f"Prefilter Policy, {ppolicy.id}, not found.  Cannot remove from HitCounts."
                )
        elif action == "clear":
            if self.prefilter_ids:
                self.prefilter_ids = []
                logging.info("All prefilter_ids removed from this HitCounts object.")

        # Rebuild the URL with possible new information
        self.URL = self.URL.split("?")[0]
        self.URL = f"{self.URL}{self.URL_SUFFIX}"

    def get(self, **kwargs):
        """
        Get HitCounts based on filter criteria
        :return:
        """
        logging.debug("In get() for HitCount class.")
        self.parse_kwargs(**kwargs)
        if self.fmc.serverVersion < self.FIRST_SUPPORTED_FMC_VERSION:
            logging.error(
                f"Your FMC version, {self.fmc.serverVersion} does not support GET of this feature."
            )
            return {"items": []}
        if self.valid_for_get() and (self.device_id or self.prefilter_ids):
            if self.dry_run:
                logging.info(
                    "Dry Run enabled.  Not actually sending to FMC.  Here is what would have been sent:"
                )
                logging.info("\tMethod = GET")
                logging.info(f"\tURL = {self.URL}")
                return False
            response = self.fmc.send_to_api(method="get", url=self.URL)
            self.parse_kwargs(**response)
            if "items" not in response:
                response["items"] = []
            return response
        else:
            logging.warning(
                "get() method failed due to failure to pass valid_for_get() test."
            )
            return False

    def put(self, **kwargs):
        logging.info(
            "Though supported by FMC, API PUT method is not yet working for HitCounts in fmcapi."
        )
        pass

    def delete(self, **kwargs):
        logging.info(
            "Though supported by FMC, API DELETE method is not yet working for HitCounts in fmcapi."
        )
        pass

    def post(self):
        logging.info("API POST method for HitCounts not supported.")
        pass


class HitCount(HitCounts):
    """Dispose of this Class after 20210101."""

    def __init__(self, fmc, **kwargs):
        warnings.resetwarnings()
        warnings.warn("Deprecated: HitCount() should be called via HitCount().")
        super().__init__(fmc, **kwargs)
