#
# Aura Engine API (https://gitlab.servus.at/aura/engine-api)
#
# Copyright (C) 2020 - The Aura Engine Team.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


import atexit
import sys

import connexion

import meta
from base.config import AuraConfig
from base.logger import AuraLogger
from base.node import NodeType
from models import db, ma
from rest import encoder
from service import ApiService
from sync import SyncJob

# Read command line parameters

config_file = None

for arg in sys.argv:
    if arg.startswith("config="):
        config_file = arg.split("config=")[1]

# App Initialization

config = AuraConfig(config_file)
logger = AuraLogger(config, "engine-api").logger
sync_job = None


def build_app(app):
    app.json_encoder = encoder.JSONEncoder
    app.config["SQLALCHEMY_DATABASE_URI"] = config.get_database_uri()
    app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
    app.config["ENV"] = "development"
    app.config["FLASK_ENV"] = "development"
    if config.get("debug_flask") == "true":
        app.config["DEBUG"] = True
    db.init_app(app)
    ma.init_app(app)
    return app


api = connexion.App(
    __name__, specification_dir="rest/swagger", arguments={"title": "AURA Engine API"}
)
api.add_api("swagger.yaml", pythonic_params=True)
app = build_app(api.app)


@app.after_request
def after_request(response):
    header = response.headers
    header["Access-Control-Allow-Origin"] = config.get("api_cors")
    return response


def startup():
    """
    Startup Server.
    """
    port = config.get("api_port")
    api.run(port=port)


def shutdown():
    """
    Called when the application shuts down.
    """
    if sync_job:
        sync_job.exit()


with app.app_context():
    """
    Initialize Server.
    """
    db.create_all()

    # Evaluate deployment mode
    node_type = NodeType.MAIN
    if config.get("host_id") == 0:
        node_type = NodeType.SYNC

    service = ApiService(config, logger, node_type)
    app.config["SERVICE"] = service

    # Run sync job only in SYNC NODE mode
    if node_type == NodeType.SYNC:
        if config.get("enable_federation") == "false":
            logger.info("Node synchronization disabled")
        else:
            sync_job = SyncJob(config, logger, app)
            sync_job.start()

    atexit.register(shutdown)
    type = "MAIN"
    if node_type == NodeType.SYNC:
        type = "SYNC"
    federation = "enabled"
    if config.get("enable_federation") == "false":
        federation = "disabled"
    splash = (
        "\n\n        ░E░N░G░I░N░E░░░A░P░I░ - v%s running as %s node - Federation %s.\n\n"
        % (meta.__version__, type, federation)
    )
    logger.info(splash)


if __name__ == "__main__":
    startup()