import requests
from ua_parser import user_agent_parser

_SUPPORT_DATA = requests.get(
    "https://raw.githubusercontent.com/Fyrd/caniuse/master/data.json"
).json()["data"]

SUPPORT = "y"
PARTIAL_SUPPORT = "a"
UNSUPPORTED = "n"
POLYFILL = "p"
UNKNOWN = "u"
PREFIX = "x"
DISABLED = "d"


def safe_int(string):
    try:
        return int(string)
    except (ValueError, TypeError):
        return 0


class BrowserFamily(object):
    def __init__(self, data):
        self._data = data
        self._ranges = ranges = []
        self._versions = versions = {}
        max_version = ()
        max_support = UNKNOWN

        for version, support in data.items():
            if version == "all":
                self.max_support = support
            elif "-" in version:
                start, end = version.split("-")
                start = tuple(map(int, start.split(".")))
                end = tuple(map(int, end.split("."))) + (1e3000,)
                ranges.append((start, end, support))
                if end > max_version:
                    max_version = end
                    max_support = support
            else:
                try:
                    version = tuple(map(int, version.split(".")))
                except ValueError:
                    pass
                else:
                    if version > max_version:
                        max_version = version
                        max_support = support
                versions[version] = support

        self.max_version = max_version
        self.max_support = max_support

    def check(self, major, minor, patch):
        int_major, int_minor, int_patch = map(safe_int, (major, minor, patch))

        version = (int_major, int_minor, int_patch)
        if version > self.max_version:
            return self.max_support

        for key in (
            (int_major, int_minor, int_patch),
            (int_major, int_minor),
            (int_major,),
            major,
        ):
            try:
                return self._versions[key]
            except KeyError:
                pass

        for start, end, support in self._ranges:
            if start <= version < end:
                return support

        return UNKNOWN


class Feat(object):
    def __init__(self, data):
        self._data = data
        self._family = {
            name: BrowserFamily(data) for name, data in data["stats"].items()
        }

    def __getitem__(self, item):
        return self._family[item]


class Database(object):
    def __init__(self, data):
        self._data = data
        self._feats = {feat: Feat(data) for feat, data in data.items()}

    def __getitem__(self, item):
        return self._feats[item]


database = Database(_SUPPORT_DATA)


class CanIUse(object):
    def __init__(self, ua):
        self._agent = user_agent_parser.Parse(ua)

        os_family = self._agent["os"]["family"]
        browser_family = self._agent["user_agent"]["family"]

        family = None

        if os_family == "Android":
            if "Firefox" in browser_family:
                family = "and_ff"
            elif "Chrome" in browser_family:
                family = "and_chr"
            elif "Android" in browser_family:
                family = "android"
        else:
            if "Edge" in browser_family:
                family = "edge"
            elif "Firefox" in browser_family:
                family = "firefox"
            elif "Chrome" in browser_family:
                family = "chrome"
            elif "IE" in browser_family:
                family = "ie"
            elif "Opera" in browser_family:
                family = "opera"
            elif "Safari" in browser_family:
                family = "safari"

        self._family = family

    def _check_feat(self, feat):
        if not self._family:
            return UNKNOWN

        try:
            stats = feat[self._family]
        except KeyError:
            return UNKNOWN
        else:
            ua = self._agent["user_agent"]
            return stats.check(ua["major"], ua["minor"], ua["patch"])[0]

    def __getattr__(self, attr):
        try:
            feat = database[attr.replace("_", "-")]
        except KeyError:
            raise AttributeError(attr)
        else:
            result = self._check_feat(feat)
            setattr(self, attr, result)
            return result
