from datetime import datetime
from hashlib import md5

from django.utils.timezone import now

from wagtail.coreutils import accepts_kwarg

from .exceptions import EmbedUnsupportedProviderException
from .finders import get_finders
from .models import Embed


def get_embed(url, max_width=None, max_height=None, finder=None):
    embed_hash = get_embed_hash(url, max_width, max_height)

    # Check database
    try:
        return Embed.objects.exclude(cache_until__lte=now()).get(hash=embed_hash)
    except Embed.DoesNotExist:
        pass

    # Get/Call finder
    if not finder:

        def finder(url, max_width=None, max_height=None):
            for finder in get_finders():
                if finder.accept(url):
                    kwargs = {}
                    if accepts_kwarg(finder.find_embed, "max_height"):
                        kwargs["max_height"] = max_height
                    return finder.find_embed(url, max_width=max_width, **kwargs)

            raise EmbedUnsupportedProviderException

    embed_dict = finder(url, max_width, max_height)

    # Make sure width and height are valid integers before inserting into database
    try:
        embed_dict["width"] = int(embed_dict["width"])
    except (TypeError, ValueError):
        embed_dict["width"] = None

    try:
        embed_dict["height"] = int(embed_dict["height"])
    except (TypeError, ValueError):
        embed_dict["height"] = None

    # Make sure html field is valid
    if "html" not in embed_dict or not embed_dict["html"]:
        embed_dict["html"] = ""

    # If the finder does not return an thumbnail_url, convert null to '' before inserting into the db
    if "thumbnail_url" not in embed_dict or not embed_dict["thumbnail_url"]:
        embed_dict["thumbnail_url"] = ""

    # Create database record
    embed, created = Embed.objects.update_or_create(
        hash=embed_hash, defaults=dict(url=url, max_width=max_width, **embed_dict)
    )

    # Save
    embed.last_updated = datetime.now()
    embed.save()

    return embed


def get_embed_hash(url, max_width=None, max_height=None):
    h = md5()
    h.update(url.encode("utf-8"))
    if max_width is not None:
        h.update(b"\n")
        h.update(str(max_width).encode("utf-8"))
    if max_height is not None:
        h.update(b"\n")
        h.update(str(max_height).encode("utf-8"))
    return h.hexdigest()
