from bs4 import BeautifulSoup
from flask import current_app
from flask import request, make_response, render_template, url_for, Blueprint
from redwind import hooks
from redwind import util
from redwind.extensions import db
from redwind.models import Post, Mention, get_settings
from redwind.tasks import get_queue, async_app_context
from werkzeug.exceptions import NotFound
import datetime
import mf2py
import mf2util
import requests
import urllib.parse
import urllib.request

wm_receiver = Blueprint('wm_receiver', __name__)


class MentionResult:
    def __init__(self, mention, create):
        self.mention = mention
        self.create = create


class ProcessResult:
    def __init__(self, post=None, error=None, delete=False):
        self.post = post
        self.error = error
        self.delete = delete
        self.mention_results = []

    def add_mention(self, mention, create):
        self.mention_results.append(MentionResult(mention, create))

    @property
    def mentions(self):
        return [r.mention for r in self.mention_results]


def register(app):
    app.register_blueprint(wm_receiver)


@wm_receiver.route('/webmention', methods=['GET', 'POST'])
def receive_webmention():
    if request.method == 'GET':
        return render_template('webmention.jinja2')

    source = request.form.get('source')
    target = request.form.get('target')
    callback = request.form.get('callback')

    if not source:
        return make_response(
            'webmention missing required source parameter', 400)

    if not target:
        return make_response(
            'webmention missing required target parameter', 400)

    current_app.logger.debug(
        "Webmention from %s to %s received", source, target)

    job = get_queue().enqueue(
        do_process_webmention, source, target, callback, current_app.config)
    status_url = url_for('.webmention_status', key=job.id, _external=True)

    return make_response(
        render_template('wm_received.jinja2', status_url=status_url), 202)


@wm_receiver.route('/webmention/status/<key>')
def webmention_status(key):
    job = get_queue().fetch_job(key)

    if not job:
        rv = {
            'response_code': 400,
            'status': 'unknown',
            'reason': 'Job does not exist or its status has expired',
        }

    elif job.result == 'queued':
        rv = {
            'response_code': 202,
            'status': 'queued',
            'reason': 'Mention has been queued for processing',
        }
    else:
        rv = job.result or {}

    return make_response(
        render_template('wm_status.jinja2', **rv),
        rv.get('response_code', 400))


def do_process_webmention(source, target, callback, app_config):
    def call_callback(result):
        if callback:
            requests.post(callback, data=result)
    with async_app_context(app_config):