#!/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 time
import sys

import redis

from argparse import ArgumentParser

from modules.cli.padavan import Padavan
from modules.base.exceptions import PlaylistException
from modules.base.config import AuraConfig


class Guru():
    """
        Command Line Interface (CLI) for Aura Engine.
    """
    # config_path = "%s/configuration/engine.ini" % Path(__file__).parent.absolute()
    config = AuraConfig()
    parser = None
    args = None

    # ------------------------------------------------------------------------------------------ #
    def __init__(self):
        self.init_argument_parser()
        self.handle_arguments()

    def handle_arguments(self):
        if self.args.stoptime:
            start = time.time()

        if not self.args.quiet:
            print("Guru thinking...")

        try:
            p = Padavan(self.args, self.config)
            p.meditate()
        except PlaylistException as pe:
            # typically there is no next file found
            if not self.args.quiet:
                print(pe)
            else:
                print("")
            exit(4)
        except redis.exceptions.TimeoutError:
            print("Timeout when waiting for redis message. Is AURA daemon running? Exiting...")
            exit(3)

        if not self.args.quiet:
            print("...result: ")

        if p.stringreply != "":
            #print(p.stringreply)
            if p.stringreply[len(p.stringreply)-1] == "\n":
                print(p.stringreply[0:len(p.stringreply) - 1])
            else:
                print(p.stringreply[0:len(p.stringreply)])

        if self.args.stoptime:
            end = time.time()
            exectime = end-start
            print("execution time: "+str(exectime)+"s")

    def init_argument_parser(self):

        try:
            self.create_parser()
            self.args = self.parser.parse_args()

        except (ValueError, TypeError) as e:
            if self.parser is not None:
                self.parser.print_help()
            print()
            print(e)
            exit(1)

    def create_parser(self):
        self.parser = ArgumentParser()

        # options
        self.parser.add_argument("-sep", "--stop-execution-time", action="store_true", dest="stoptime",   default=False, help="Prints the execution time at the end of the skript")
        self.parser.add_argument("-q",   "--quiet",               action="store_true", dest="quiet",      default=False, help="Just the result will outputed to stout")
        self.parser.add_argument("-rd",  "--recreate-database",   action="store_true", dest="recreatedb", default=False, help="Do you want to recreate the database?")

        # getter
        self.parser.add_argument("-pcs", "--print-connection-status", action="store_true", dest="get_connection_status",  default=False, help="Prints the status of the connection to liquidsoap, pv and tank")
        self.parser.add_argument("-gam", "--get-active-mixer",        action="store_true", dest="mixer_channels_selected",default=False, help="Which mixer channels are selected?")
        self.parser.add_argument("-pms", "--print-mixer-status",      action="store_true", dest="mixer_status",           default=False, help="Prints all mixer sources and their states")
        self.parser.add_argument("-pap", "--print-act-programme",     action="store_true", dest="get_act_programme",      default=False, help="Prints the actual Programme, the controller holds")
        self.parser.add_argument("-s",   "--status",                  action="store_true", dest="get_status",             default=False, help="Returns the Engine Status as JSON")

        # liquid manipulation
        self.parser.add_argument("-am", "--select-mixer",    action="store", dest="select_mixer",   default=-1, metavar="MIXERNAME",                     help="Which mixer should be activated?")
        self.parser.add_argument("-dm", "--de-select-mixer", action="store", dest="deselect_mixer", default=-1, metavar="MIXERNAME",                     help="Which mixer should be activated?")
        self.parser.add_argument("-vm", "--volume",          action="store", dest="set_volume",     default=0,  metavar=("MIXERNUM", "VOLUME"), nargs=2, help="Set volume of a mixer source", type=int)

        # shutdown server
        self.parser.add_argument("-sd", "--shutdown", action="store_true", dest="shutdown", default=False, help="Shutting down aura server")

        # playlist in/output
        self.parser.add_argument("-fnp", "--fetch-new-programmes",  action="store_true", dest="fetch_new_programme",   default=False, help="Fetch new programmes from api_steering_calendar in engine.ini")
        self.parser.add_argument("-pmq", "--print-message-queue",   action="store_true", dest="print_message_queue",   default=False, help="Prints message queue")

        # send a redis message
        self.parser.add_argument("-rm", "--redis-message", action="store", dest="redis_message", default=False, metavar=("CHANNEL", "MESSAGE"), nargs=2, help="Send a redis message to the Listeners")

        # calls from liquidsoap
        self.parser.add_argument("-gnf", "--get-next-file-for", action="store",      dest="get_file_for", default=False, metavar="PLAYLISTTYPE",                      help="For which type you wanna GET a next audio file?")
        self.parser.add_argument("-snf", "--set-next-file-for", action="store",      dest="set_file_for", default=False, metavar=("PLAYLISTTYPE", "FILE"), nargs=2,   help="For which type you wanna SET a next audio file?")
        self.parser.add_argument("-np",  "--now-playing",       action="store_true", dest="now_playing",  default=False,                                              help="Which source is now playing")
        
        self.parser.add_argument("-ip",  "--init-player",       action="store_true", dest="init_player",  default=False,                                              help="Reset liquidsoap volume and mixer activations?")
        self.parser.add_argument("-ts",  "--on_play",           action="store",      dest="on_play",      default=False, metavar="INFO",                              help="Event handling when some entry started playing")

        if len(sys.argv) == 1:
            raise ValueError("No Argument passed!")


def valid_playlist_entry(argument):
    from datetime import datetime

    try:

        index = int(argument[0])
        fromtime = datetime.strptime(argument[1], "%Y-%m-%d")
        source = argument[2]
        return index, fromtime, source
    except:
        msg = "Not a valid date: '{0}'.".format(argument[0])
        print(msg)
        raise


# # ## ## ## ## ## # #
# # ENTRY FUNCTION # #
# # ## ## ## ## ## # #
def main():
    Guru()
# # ## ## ## ## ## ## # #
# # End ENTRY FUNCTION # #
# # ## ## ## ## ## ## # #


if __name__ == "__main__":
    main()