/*
	main.cpp

	Starting point for the myth lcd server daemon

*/

#include <qapplication.h>
#include <qsqldatabase.h>
#include <qfile.h>
#include <qtextstream.h>

#include <iostream>
using namespace std;
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>

#include "exitcodes.h"
#include "mythcontext.h"
#include "mythdbcon.h"
#include "tv_play.h"
#include "compat.h"

#include "lcdserver.h"

#define LCD_EXIT_DAEMONIZING_ERROR                FRONTEND_EXIT_START-1
#define LCD_EXIT_NO_TRANSCODE_SUPPORT             FRONTEND_EXIT_START-2

int main(int argc, char **argv)
{
    QApplication a(argc, argv, false);
    bool daemon_mode = false;
    int  special_port = -1;    
    QString startup_message = "";          // default to no startup message
    int message_time = 30;                 // time to display startup message  
    print_verbose_messages = VB_IMPORTANT; // only show important messages
    QString logfile = "";
    
    debug_level = 0;                       // don't show any debug messages by default 
    
    //  Check command line arguments
    for (int argpos = 1; argpos < a.argc(); ++argpos)
    {
        
        if (!strcmp(a.argv()[argpos],"-d") ||
            !strcmp(a.argv()[argpos],"--daemon"))
        {
            daemon_mode = true;
        }
        else if (!strcmp(a.argv()[argpos],"-n") ||
            !strcmp(a.argv()[argpos],"--nodaemon"))
        {
            daemon_mode = false;
        }
        else if (!strcmp(a.argv()[argpos],"-p") ||
            !strcmp(a.argv()[argpos],"--port"))
        {
            if (a.argc() > argpos)
            {
                QString port_number = a.argv()[argpos+1];
                ++argpos;
                special_port = port_number.toInt();
                if (special_port < 1 || special_port > 65534)
                {
                    VERBOSE(VB_IMPORTANT, "lcdserver: Bad port number");
                    return FRONTEND_EXIT_INVALID_CMDLINE;
                }
            } 
            else 
            {
                VERBOSE(VB_IMPORTANT, "lcdserver: Missing argument to "
                                "-p/--port option");
                return FRONTEND_EXIT_INVALID_CMDLINE;
            }
        }
        else if (!strcmp(a.argv()[argpos],"-m") ||
            !strcmp(a.argv()[argpos],"--startupmessage"))
        {
            if (a.argc() > argpos)
            {
                startup_message = a.argv()[argpos+1];
                ++argpos;
            } 
            else 
            {
                VERBOSE(VB_IMPORTANT, "lcdserver: Missing argument to "
                                "-m/--startupmessage");
                return FRONTEND_EXIT_INVALID_CMDLINE;
            }
        }
        else if (!strcmp(a.argv()[argpos],"-t") ||
            !strcmp(a.argv()[argpos],"--messagetime"))
        {
            if (a.argc() > argpos)
            {
                QString sTime = a.argv()[argpos+1];
                ++argpos;
                message_time = sTime.toInt();
                if (message_time < 1 || message_time > 1000)
                {
                    VERBOSE(VB_IMPORTANT, "lcdserver: Bad show message time");
                    return FRONTEND_EXIT_INVALID_CMDLINE;
                }
            } 
            else 
            {
                VERBOSE(VB_IMPORTANT, "lcdserver: Missing argument to "
                                "-t/--messagetime");
                return FRONTEND_EXIT_INVALID_CMDLINE;
            }
        }
        else if (!strcmp(a.argv()[argpos],"-v") ||
            !strcmp(a.argv()[argpos],"--verbose"))
        {
            if (a.argc()-1 > argpos)
            {
                if (parse_verbose_arg(a.argv()[argpos+1]) ==
                        GENERIC_EXIT_INVALID_CMDLINE)
                    return FRONTEND_EXIT_INVALID_CMDLINE;

                ++argpos;
            } 
            else
            {
                cerr << "Missing argument to -v/--verbose option\n";
                return FRONTEND_EXIT_INVALID_CMDLINE;
            }
        }    
        else if (!strcmp(a.argv()[argpos],"-l") ||
            !strcmp(a.argv()[argpos],"--logfile"))
        {
            if (a.argc()-1 > argpos)
            {
                logfile = a.argv()[argpos+1];
                if (logfile.startsWith("-"))
                {
                    cerr << "Invalid or missing argument to -l/--logfile option\n";
                    return FRONTEND_EXIT_INVALID_CMDLINE;
                }
                else
                {
                    ++argpos;
                }
            }
            else
            {
                cerr << "Missing argument to -l/--logfile option\n";
                return FRONTEND_EXIT_INVALID_CMDLINE;
            }
        }
        else if (!strcmp(a.argv()[argpos],"-x") ||
            !strcmp(a.argv()[argpos],"--debuglevel"))
        {
            if (a.argc() > argpos)
            {
                QString sTemp = a.argv()[argpos+1];
                
                ++argpos;
                debug_level = sTemp.toInt();
                if (debug_level < 0 || debug_level > 10)
                {
                    VERBOSE(VB_IMPORTANT, "lcdserver: Bad debug level");
                    return FRONTEND_EXIT_INVALID_CMDLINE;
                }
            } 
            else 
            {
                VERBOSE(VB_IMPORTANT, "lcdserver: Missing argument to "
                                "-x/--debuglevel");
                return FRONTEND_EXIT_INVALID_CMDLINE;
            }
        }
        else
        {
            cerr << "Invalid argument: " << a.argv()[argpos] << endl <<
                    "Valid options are: " << endl <<
                    "-p or --port number           A port number to listen on (default is 6545) " << endl <<
                    "-d or --daemon                Runs lcd server as a daemon " << endl <<
                    "-n or --nodaemon              Does not run lcd server as a daemon (default)" << endl <<
                    "-m or --startupmessage        Message to show at startup" << endl <<
                    "-t or --messagetime           How long to show startup message (default 30 seconds)" << endl << 
                    "-l or --logfile filename      Writes STDERR and STDOUT messages to filename" << endl <<
                    "-v or --verbose debug-level    Use '-v help' for level info" << endl <<
                    "-x or --debuglevel level      Control how much debug messages to show" << endl <<
                    "                              [number between 0 and 10] (default 0)" << endl;
            return FRONTEND_EXIT_INVALID_CMDLINE;
        }
    }
    
    // set up log file
    int logfd = -1;

    if (logfile != "")
    {
        logfd = open(logfile.ascii(), O_WRONLY|O_CREAT|O_APPEND, 0664);
 
        if (logfd < 0)
        {
            perror("open(logfile)");
            return FRONTEND_EXIT_OPENING_LOGFILE_ERROR;
        }
    }

    if (logfd != -1)
    {
        // Send stdout and stderr to the logfile
        dup2(logfd, 1);
        dup2(logfd, 2);

        // Close the unduplicated logfd
        if (logfd != 1 && logfd != 2)
            close(logfd);
    }

    if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
        cerr << "Unable to ignore SIGPIPE\n";

    //  Switch to daemon mode?
    if (daemon_mode)
    {
        if (daemon(0, 1) < 0)
        {
            VERBOSE(VB_IMPORTANT, "lcdserver: Failed to run as a daemon. "
                            "Bailing out.");
            return LCD_EXIT_DAEMONIZING_ERROR;
        }
        cout << endl;
    }

    //  Get the Myth context and db hooks
    gContext = NULL;
    gContext = new MythContext(MYTH_BINARY_VERSION);
    if (!gContext->Init(false))
    {
        VERBOSE(VB_IMPORTANT, "lcdserver: Could not initialize myth context. "
                        "Exiting.");
        return FRONTEND_EXIT_NO_MYTHCONTEXT;
    }

    gContext->ConnectToMasterServer(false);

    //  Figure out port to listen on
    int assigned_port = gContext->GetNumSetting("LCDServerPort", 6545);
    if (special_port > 0)
    {
        assigned_port = special_port;
    }
   
    new LCDServer(assigned_port, startup_message, message_time);
    
    a.exec();
                                
    delete gContext;
    return FRONTEND_EXIT_OK;
}

