import datetime
from nba.exceptions import ApiError


def clean_time(col):
    """
    Parse a UTC time column to datetime.

    :param col: column to be parsed.
    :returns: datetime column
    :rtype: series

    """
    return col.apply(lambda x: datetime.datetime.strptime(x, "%Y-%m-%dT%H:%M:%S.%fZ"))


def filter_dicts(d):
    """
    Filter dict to remove None values.

    :param d: data to filter
    :type d: dict
    :returns: filtered data
    :rtype: dict

    """
    return dict((k, v) for k, v in d.items() if v is not None)


def clean_locals(params):
    """
    Clean up locals dict, remove empty and self params.

    :params params: locals dicts from a function.
    :type params: dict
    :returns: cleaned locals dict to use as params for functions
    :rtype: dict
    """
    return HDict(
        dict(
            (clean_param_key(k), HDict(v))
            if isinstance(v, dict)
            else (clean_param_key(k), tuple(v))
            if isinstance(v, list)
            else (clean_param_key(k), v)
            for k, v in params.items()
            if v is not None and k not in ["self", "session", "idx_data"]
        )
    )


def clean_param_key(key):
    return "".join(
        [k.upper() if k in ["id", "po"] else k.title() for k in key.split("_")]
    )


def check_status_code(response, codes=None):
    """Checks response.status_code is in codes
    :param response: Requests response
    :param codes: List of accepted codes or callable
    :raises: StatusCodeError if code invalid
    """
    codes = codes or [200]
    if response.status_code not in codes:
        raise ApiError(response)


class HDict(dict):
    def __hash__(self):
        return hash(frozenset(self.items()))
