#
# 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 pkg_resources

from aura_engine_api.base.config import AuraConfig
from aura_engine_api.base.logger import AuraLogger
from aura_engine_api.base.node import NodeType
from aura_engine_api.models import db, ma
from aura_engine_api.service import ApiService
from aura_engine_api.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]
if not config_file:
    config_file = "/etc/aura/engine-api.ini"

# App Initialization

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


def build_app(app):
    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
        # os.environ["FLASK_DEBUG"] = "1"
        # os.environ["FLASK_ENV"] = "development"

    db.init_app(app)
    ma.init_app(app)
    return app


app = connexion.App(
    __name__, specification_dir="rest/swagger", arguments={"title": "AURA Engine API"}
)
app.add_api("swagger.yaml", pythonic_params=True)
app = build_app(app.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")
    app.run(port=port)


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


def get_version():
    """
    Retrieve current version from `pyproject.toml`
    """
    app_version = pkg_resources.get_distribution("aura-engine-api").version
    return app_version


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        Engine API - v%s running as %s node - Federation %s.\n\n" % (
        get_version(),
        type,
        federation,
    )
    logger.info(splash)


if __name__ == "__main__":
    startup()