#!/usr/bin/python3
from abc import ABCMeta

import tornado.web

import os
import subprocess
from datetime import datetime
import isodate

import json

import util
from auth import AuthProvider
from gitmgr import GitManagerConfiguration, GitManager


startup_timestamp = datetime.now()


class HealthHandler(tornado.web.RequestHandler, metaclass=ABCMeta):
    # noinspection PyAttributeOutsideInit
    def initialize(self, sources=None):
        self.git_version = self._load_git_version()
        self.sources = sources

    @staticmethod
    def _load_git_version():
        v = None

        # try file git-version.txt first
        gitversion_file = "git-version.txt"
        if os.path.exists(gitversion_file):
            with open(gitversion_file) as f:
                v = f.readline().strip()

        # if not available, try git
        if v is None:
            try:
                v = subprocess.check_output(["git", "describe", "--always", "--dirty"],
                                            cwd=os.path.dirname(__file__)).strip().decode()
            except subprocess.CalledProcessError as e:
                print("Checking git version lead to non-null return code ", e.returncode)

        return v

    def get(self):
        health = dict()
        health['api-version'] = 'v0'

        if self.git_version is not None:
            health['git-version'] = self.git_version

        health['timestamp'] = isodate.datetime_isoformat(datetime.now())
        health['uptime'] = isodate.duration_isoformat(datetime.now() - startup_timestamp)

        if self.sources:
            for s in self.sources:
                h = s()
                if h is not None:
                    health = {**health, **h}

        self.set_header("Content-Type", "application/json")
        self.write(json.dumps(health, indent=4))
        self.set_status(200)


class Oas3Handler(tornado.web.RequestHandler, metaclass=ABCMeta):
    def get(self):
        self.set_header("Content-Type", "text/plain")
        # This is the proposed content type,
        # but browsers like Firefox try to download instead of display the content
        # self.set_header("Content-Type", "text/vnd.yml")
        with open('OAS3.yml', 'r') as f:
            oas3 = f.read()
            self.write(oas3)
        self.finish()


def make_app(_auth_provider=None, gitmgr=None):
    version_path = r"/v[0-9]"
    return tornado.web.Application([
        (version_path + r"/health", HealthHandler,
         {"sources": [lambda: {"git-head":  gitmgr.head_sha}] if gitmgr else None}),
        (version_path + r"/oas3", Oas3Handler),
    ])


def main():
    port = util.load_env('PORT', 8080)

    # Setup
    auth_provider = AuthProvider.from_environment()

    gitcfg = GitManagerConfiguration.from_environment()
    gitmgr = GitManager(configuration=gitcfg)
    gitmgr.setup()
    gitmgr.printout()

    util.run_tornado_server(make_app(auth_provider, gitmgr),
                            server_port=port)

    # Teardown
    gitmgr.teardown()

    print("Server stopped")


if __name__ == "__main__":
    main()