"""
Core web application views.

:copyright: Copyright 2013-2017, Dorian Pula <dorian.pula@amber-penguin-software.ca>
:license: AGPL v3+
"""

import http
import io
import json
import logging
import os

import flask
import invoke

import rookeries
from rookeries.main import rookeries_app
from rookeries.pages import views as page_views
from rookeries.sites import views as site_views

logger = logging.getLogger(__name__)

GIT_REVISION_INFO_FILE = './git-info'


def get_git_revision():
    if not os.path.exists(GIT_REVISION_INFO_FILE):
        return 'UNKNOWN'

    with io.open(GIT_REVISION_INFO_FILE) as git_info:
        revision_info = git_info.readlines()[0].strip()
    return revision_info or 'UNKNOWN'


@rookeries_app.route('/status')
def app_status():
    """
    Simple view that returns the status of the application.
    Useful as a part of a heartbeat mechanism.
    """
    app_status_info = {
        'app': 'rookeries',
        'version': rookeries.__version__,
        'gitRevision': get_git_revision(),
    }

    return flask.jsonify(app_status_info)


@rookeries_app.route('/api')
@rookeries_app.route('/api/<path:some_path>')
def render_catch_all_for_api_calls(some_path=''):
    flask.abort(http.HTTPStatus.NOT_FOUND)


def extract_json_response(response: flask.Response):
    return json.loads(response.get_data().decode())


@rookeries_app.route('/')
@rookeries_app.route('/<path:some_path>')
def render_single_page_app(some_path=''):
    # TODO: Clean this rendering significantly.
    # TODO: Check if site and page are present.  If not exit early.
    # TODO: Consider using internal calls to site and page views::
    # TODO: https://gist.github.com/lost-theory/3005268
    status_code = http.HTTPStatus.OK

    page_info = {
        'path': some_path,
    }
    site_info = {}
    server_side_response = ''
    site_response = site_views.get_site()

    try:
        page_response = page_views.serve_page(slug=some_path)
        page_info['title'] = page_response['title']
        site_info = extract_json_response(site_response)

        # TODO: If no page given, use the default page of a site.
        response = invoke.run(f'node dist/server.js /{some_path}')
        server_side_response = response.stdout
    except Exception:
        logger.warning(Exception)

    # TODO: Update site and page info with good defaults
    site_info['name'] = 'Rookeries'
    site_info['favicon'] = site_info.get(
        'favicon',
        '/static/images/mr-penguin-amber-favicon.ico')
    page_info['title'] = page_info.get('title', 'Unknown Page')

    # TODO: Handle errors when calling the server side code better.
    return flask.render_template(
        'base.html', react_render=server_side_response, site=site_info,
        page=page_info), status_code
