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