# author: Alex Savatieiev (osavatieiev@mirantis.com)
from gevent import monkey, pywsgi
monkey.patch_all()
import falcon # noqa E402
import os # noqa E402
import json # noqa E402

from copy import deepcopy # noqa E402
from platform import system, release, node # noqa E402

from cfg_checker.common.settings import pkg_dir  # noqa E402
from cfg_checker.helpers.falcon_jinja2 import FalconTemplate  # noqa E402
from .fio_runner import FioProcessShellRun, get_time # noqa E402

template = FalconTemplate(
    path=os.path.join(pkg_dir, "templates")
)

_module_status = {
    "status": "unknown",
    "healthcheck": {},
    "actions": [],
    "options": {},
    "uri": "<agent_uri>/api/<modile_name>",
}

_action = {
    "module": "<name>",
    "action": "<action>",
    "options": "<options_dict>"
}

_modules = {
    "fio": deepcopy(_module_status)
}

_status = {
    "agent": {
        "started": get_time()
    },
    "modules": list(_modules.keys()),
    "help": {
        ".../api": {
            "GET": "<this_status>",
            "POST": json.dumps(_action)
        },
        ".../api/<module_name>": {
            "GET": "returns healthcheck and module help"
        }
    }
}

# Populate modules
_fio = FioProcessShellRun()


def _init_status(mod):
    _modules[mod]["uri"] = "<agent_uri>/api/fio"
    _modules[mod]["actions"] = list(_fio.actions.keys())


def _update_status(mod):
    _modules[mod]["healthcheck"] = _fio.hchk
    _modules[mod]["options"] = _fio.get_options()
    _modules[mod].update(_fio.status())


class FioStatus:
    _name = "fio"

    def on_get(self, req, resp):
        # Hacky way to handle empty request
        _m = req.get_media(default_when_empty={})
        if "fast" in _m and _m["fast"]:
            resp.status = falcon.HTTP_200
            resp.content_type = "application/json"
            resp.text = json.dumps(_fio.status())
        else:
            _update_status(self._name)

            resp.status = falcon.HTTP_200
            resp.content_type = "application/json"
            resp.text = json.dumps(_modules[self._name])


class Api:
    def on_get(self, req, resp):
        # return api status
        resp.status = falcon.HTTP_200
        resp.content_type = "application/json"
        resp.text = json.dumps(_status)

    def on_post(self, req, resp):
        def _resp(resp, code, msg):
            resp.status = code
            resp.content_type = "application/json"
            resp.text = json.dumps({"error": msg})
        # Handle actions
        _m = req.get_media(default_when_empty={})
        if _m:
            # Validate action structure
            _module = _m.get('module', "")
            _action = _m.get('action', "")
            _options = _m.get('options', {})

            if not _module or _module not in list(_modules.keys()):
                _resp(
                    resp,
                    falcon.HTTP_400,
                    "Invalid module '{}'".format(_module)
                )
                return
            elif not _action or _action not in _modules[_module]['actions']:
                _resp(
                    resp,
                    falcon.HTTP_400,
                    "Invalid action '{}'".format(_action)
                )
                return
            else:
                # Handle command
                _a = _fio.actions[_action]
                if _action == 'get_options':
                    resp.status = falcon.HTTP_200
                    resp.content_type = "application/json"
                    resp.text = json.dumps({"options": _a()})
                elif _action == 'get_resultlist':
                    resp.status = falcon.HTTP_200
                    resp.content_type = "application/json"
                    resp.text = json.dumps({"resultlist": _a()})
                elif _action == 'get_result':
                    if 'time' not in _options:
                        _resp(
                            resp,
                            falcon.HTTP_400,
                            "No 'time' found for '{}'".format(_action)
                        )
                        return
                    _time = _options['time']
                    resp.status = falcon.HTTP_200
                    resp.content_type = "application/json"
                    resp.text = json.dumps({_time: _a(_time)})
                elif _action == 'do_singlerun':
                    _a(_options)
                    resp.status = falcon.HTTP_200
                    resp.content_type = "application/json"
                    resp.text = json.dumps({"ok": True})
                elif _action == 'do_scheduledrun':
                    # prepare scheduled run

                    # Run it
                    _a(_options)
                    resp.status = falcon.HTTP_200
                    resp.content_type = "application/json"
                    resp.text = json.dumps({"ok": True})
                else:
                    _resp(
                        resp,
                        falcon.HTTP_500,
                        "Unknown error happened for '{}/{}/{}'".format(
                            _module,
                            _action,
                            _options
                        )
                    )
                return
        else:
            _resp(resp, falcon.HTTP_400, "Empty request body")


class Index:
    @template.render("agent_index_html.j2")
    def on_get(self, request, response):
        # prepare template context
        _context = {
            "gen_date": get_time(),
            "system": system(),
            "release": release(),
            "hostname": node()
        }
        _context.update(_status)
        # creating response
        response.status = falcon.HTTP_200
        response.content_type = "text/html"
        response.context = _context


def agent_server(host="0.0.0.0", port=8765):
    # init api
    api = falcon.API()
    # populate pages
    api.add_route("/", Index())
    api.add_route("/api/", Api())

    # Populate modules list
    _active_modules = [FioStatus]
    # init modules
    for mod in _active_modules:
        _init_status(mod._name)
        _update_status(mod._name)

        api.add_route("/api/"+mod._name, mod())

    # init and start server
    server = pywsgi.WSGIServer((host, port), api)
    server.serve_forever()
