# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, you can obtain one at http://mozilla.org/MPL/2.0/.
import os

import commonmark
from django.conf import settings
from django.http import HttpResponse
from django.shortcuts import render
from django.utils.functional import cached_property
from pkg_resources import parse_version


class News:
    """
    Encapsulate the rendering of the news document ``NEWS.md``.
    """

    def __init__(self):
        self.path = os.path.join(settings.BASE_DIR, "NEWS.md")
        self.parser = commonmark.Parser()
        self.renderer = commonmark.HtmlRenderer()
        self.cookie_name = "news_current"

    @cached_property
    def ast(self):
        """
        Return (and cache for repeated querying) the Markdown AST
        of the ``NEWS.md`` file.
        """
        with open(self.path, "r") as news_file:
            content = news_file.read()
            return self.parser.parse(content)

    @cached_property
    def latest(self):
        """
        Return the latest version found in the ``NEWS.md`` file.
        """
        version = self.ast.first_child.literal
        if not version:
            version = self.ast.first_child.first_child.literal
            if not version:
                version = "0.0"
        return version

    def render(self):
        "Render the ``NEWS.md`` file as a HTML."
        return self.renderer.render(self.ast)

    def update(self, request, response):
        "Set the cookie for the given request with the latest seen version."
        if not self.uptodate(request):
            response.set_cookie(
                self.cookie_name, self.latest, secure=True, httponly=True
            )

    def current(self, request):
        "Return the latest seen version or nothing."
        return request.COOKIES.get(self.cookie_name) or ""

    def uptodate(self, request):
        "Return whether the current is newer than the last seen version."
        return parse_version(self.latest) <= parse_version(self.current(request))


def list_news(request):
    """
    View to list all news and optionally render only part of the
    template for AJAX requests.
    """
    news = News()

    if request.is_ajax():
        response = HttpResponse(news.render())
    else:
        context = {"news": news}
        response = render(request, "atmo/news/list.html", context)

    news.update(request, response)
    return response


def check_news(request):
    """
    View to check if the current user has seen the latest "News" section
    and return either `'ok'` or `'meh'` as a string.
    """
    news = News()
    if news.uptodate(request):
        return HttpResponse("ok")
    else:
        return HttpResponse("meh")
