#!/bin/sh
''''which python3.8 >/dev/null 2>&1 && exec python3.8 "$0" "$@"     # '''
''''which python3.7  >/dev/null 2>&1 && exec python3.7  "$0" "$@"   # '''
''''exec echo "Error: Snaaakey Python, where are you?"                # '''

#
# Aura Engine (https://gitlab.servus.at/aura/engine)
#
# Copyright (C) 2017-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 os
import sys
import signal
import logging
import subprocess

import time 

from flask               import Flask
from flask_sqlalchemy    import SQLAlchemy

from src.base.logger import AuraLogger
from src.base.config import AuraConfig
from src.base.utils  import SimpleUtil as SU


config = AuraConfig()
def configure_flask():
    app.config["SQLALCHEMY_DATABASE_URI"] = config.get_database_uri()
    app.config['BABEL_DEFAULT_LOCALE'] = 'de'
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

# FIXME Instatiate SQLAlchemy without the need for Flask
app = Flask(__name__)
configure_flask()
DB = SQLAlchemy(app)


class EngineRunner:
    """
    EngineRunner is in charge of

    1. Initializing the engine and all dependencies
    3. Starting Liquidsoap in a separate thread, if requested

    """
    logger = None
    config = None
    engine = None
    lqs = None


    def __init__(self):
        """
        Constructor
        """
        self.config = config
        AuraLogger(self.config)
        self.logger = logging.getLogger("AuraEngine")
        


    def run(self, start_lqs, lqs_debug_flags):
        """
        Starts Engine Core.
        """                
        from src.scheduling.scheduler import AuraScheduler
        from src.core.engine import Engine

        # Check if the database has to be re-created
        if self.config.get("recreate_db") is not None:
            AuraScheduler.init_database()

        if start_lqs:
            runner.run_lqs(lqs_debug_flags)        
        else:
            self.logger.info(SU.yellow("Please note, Liquidsoap needs to be started manually."))

        self.engine = Engine()



    def run_lqs(self, lqs_debug_flags):
        """
        Starts Liquidsoap.
        """
        debug_output = lqs_debug_flags.get("debug_output")
        verbose_output = lqs_debug_flags.get("verbose_output")
        lqs_path = self.config.get("liquidsoap_path")
        lqs_cwd = os.getcwd() + "/" + self.config.get("liquidsoap_working_dir")
        lqs_output = ""
        lqs_output = self.get_debug_flags(debug_output, verbose_output)

        self.lqs = subprocess.Popen([lqs_path, lqs_output, "engine.liq"], \
            cwd=lqs_cwd, \
            stdout=subprocess.PIPE, \
            shell=False)



    def get_lqs_cmd(self, debug_output, verbose_output):
        """
        Returns a shell command string to start Liquidsoap
        """
        lqs_path = self.config.get("liquidsoap_path")
        lqs_cwd = os.getcwd() + "/" + self.config.get("liquidsoap_working_dir")
        lqs_output = self.get_debug_flags(debug_output, verbose_output)
        return "(cd %s && %s %s ./engine.liq)" % (lqs_cwd, lqs_path, lqs_output)



    def get_debug_flags(self, debug_output, verbose_output):
        """
        Build Liquidsoap debug parameters.
        """
        output = ""
        if debug_output:
            output += "--debug " 
        if verbose_output:
            output += "--verbose "
        return output



    def exit_gracefully(self, signum, frame):
        """
        Shutdown of the engine. Also terminates the Liquidsoap thread.
        """
        if self.engine:
            self.engine.terminate()

        if self.lqs:
            self.lqs.terminate()
            self.logger.info("Terminated Liquidsoap")

        self.logger.info("Gracefully terminated Aura Engine! (signum:%s, frame:%s)" % (signum, frame))
        sys.exit(0)        



#
# START THE ENGINE
#


if __name__ == "__main__":        
    runner = EngineRunner()
    do_start_lqs = True
    lqs_cmd = False

    signal.signal(signal.SIGINT, runner.exit_gracefully)
    signal.signal(signal.SIGTERM, runner.exit_gracefully)

    if len(sys.argv) >= 2:
        if "--without-lqs" in sys.argv:
            do_start_lqs = False
        if "--get-lqs-command" in sys.argv:
            lqs_cmd = True
        if "--use-test-data" in sys.argv:
            runner.config.set("use_test_data", True)
        if "--recreate-database" in sys.argv:
            runner.config.set("recreate_db", True)

    if lqs_cmd:
        print(runner.get_lqs_cmd(True, True))
    else:                
        runner.run(do_start_lqs, { "debug_output": False, "verbose_output": False })