# =============================================================================
# Ural Google-related heuristic functions
# =============================================================================
#
# Collection of functions related to Google urls.
#
import re
from ural.utils import safe_urlsplit, unquote, pathsplit
from ural.patterns import QUERY_VALUE_IN_URL_TEMPLATE

AMP_QUERY_RE = re.compile(r"amp(_.+)=?", re.I)
AMP_SUFFIXES_RE = re.compile(r"(?:\.amp(?=\.html$)|\.amp/?$|(?<=/)amp/?$)", re.I)

URL_EXTRACT_RE = re.compile(QUERY_VALUE_IN_URL_TEMPLATE % r"url")

DRIVE_TYPES = ["document", "presentation", "spreadsheets"]


def is_amp_url(url):
    splitted = safe_urlsplit(url)

    if splitted.hostname.endswith(".ampproject.org"):
        return True

    if splitted.hostname.startswith("amp-"):
        return True

    if splitted.hostname.startswith("amp."):
        return True

    if "/amp/" in splitted.path:
        return True

    if AMP_SUFFIXES_RE.search(splitted.path):
        return True

    if splitted.query and AMP_QUERY_RE.search(splitted.query):
        return True

    return False


def is_google_link(url):
    splitted = safe_urlsplit(url)

    if not splitted.hostname or "google." not in splitted.hostname:
        return False

    if splitted.path != "/url":
        return False

    return True


def extract_url_from_google_link(url):
    m = URL_EXTRACT_RE.search(url)

    if m is None:
        return None

    return unquote(m.group(1))


class GoogleDriveParsedItem(object):
    def __eq__(self, other):
        if self.__class__ != other.__class__:
            return False

        for attr in self.__slots__:
            if getattr(self, attr) != getattr(other, attr):
                return False

        return True

    def __repr__(self):
        class_name = self.__class__.__name__

        representation = "<" + class_name

        for key in self.__slots__:
            value = getattr(self, key)

            if value is None:
                continue

            representation += " %s=%s" % (key, value)

        representation += ">"

        return representation


class GoogleDriveFile(GoogleDriveParsedItem):
    __slots__ = ("type", "id")

    def __init__(self, _type, _id):
        self.type = _type
        self.id = _id

    @property
    def url(self):
        return "https://docs.google.com/%s/d/%s" % (self.type, self.id)

    def get_export_url(self, format="csv"):
        return "https://docs.google.com/%s/d/%s/export?exportFormat=%s" % (
            self.type,
            self.id,
            format,
        )


class GoogleDrivePublicLink(GoogleDriveParsedItem):
    __slots__ = ("type", "id")

    def __init__(self, _type, _id):
        self.type = _type
        self.id = _id

    @property
    def url(self):
        return "https://docs.google.com/%s/d/e/%s/pub" % (self.type, self.id)

    def get_export_url(self, format="csv"):
        return "https://docs.google.com/%s/d/e/%s/pub?output=%s" % (
            self.type,
            self.id,
            format,
        )


def parse_google_drive_url(url):
    splitted = safe_urlsplit(url)

    if "docs.google.com" not in splitted.netloc:
        return None

    path = pathsplit(splitted.path)

    if len(path) < 3:
        return None

    drive_type = path[0]

    if drive_type not in DRIVE_TYPES:
        return None

    if path[1] != "d":
        return None

    if path[-1] == "pub":
        if path[2] != "e":
            return None

        return GoogleDrivePublicLink(drive_type, path[3])

    return GoogleDriveFile(drive_type, path[2])


def extract_id_from_google_drive_url(url):
    parsed = parse_google_drive_url(url)

    if isinstance(parsed, GoogleDriveFile):
        return parsed.id

    return None
