/** 
 * @defgroup prefs prefs
 * preference-file routines
 * @{
 */

#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
#include <libxml/parserInternals.h>
#include <gst/gst.h>
#include <gst/interfaces/tuner.h>
#include <gst/interfaces/tunerchannel.h>
#include "include/source.h"
#include "include/x11.h"
#include "include/util.h"


static struct Prefs
{
    int verbose;            /** verbosity level */
    int quiet;              /** for beeing quiet */
    int persistent;         /** if unset, detach from terminal */
    char *xml_filename;     /** name of config-file */
    xmlParserCtxtPtr xml_parser;
    xmlDocPtr xml_doc;
    xmlNodePtr root_node;
}prefs;

/********************* getter/setter for local variables *********************/
/**
 * prefs.verbose getter
 */
int prefs_get_verbose()
{
    return prefs.verbose;
}
/**
 * util.verbose setter
 */
void prefs_set_verbose(int v)
{
    prefs.verbose = v;
}
/**
 * prefs.quiet getter
 */
int prefs_get_quiet()
{
    return prefs.quiet;
}
/**
 * prefs.quiet setter
 */
void prefs_set_quiet(int q)
{
    prefs.quiet = q;
}
/**
 * prefs.xml_doc getter
 */
xmlDocPtr prefs_get_xml()
{
    return prefs.xml_doc;
}
/************************** Module **************************/
/**
 * fetch an xml-node by it's name, node is the node 
 * to start searching recursivley 
 */
xmlNodePtr get_xml_node(char *nodeName, xmlDocPtr doc, xmlNode * node)
{
    xmlNode *tempNode, *resultNode = NULL, *nextChild;

     _VERBOSE2 printf("get_xml_node(): looking for \"%s\" in \"%s\"\n",
     nodeName, node->name);

    /*
     * main search-loop 
     */
    for(tempNode = node; tempNode && resultNode == NULL;
        tempNode = tempNode->next) {
        /*
         * check if we really got a node 
         */
        if(tempNode->type == XML_ELEMENT_NODE) {
            // _VERBOSE2 printf(" -> %s\n", tempNode->name);
            /*
             * check if it's our node we found 
             */
            if(xmlStrcmp(tempNode->name, (const xmlChar *) nodeName) == 0) {
                resultNode = tempNode;
                break;
            }
            /*
             * check possible childs of node... 
             */
            for(nextChild = xmlGetLastChild(tempNode);
                nextChild && resultNode == NULL; nextChild = nextChild->prev)
            {
                // _VERBOSE2 printf(" --> %s\n", nextChild->name);
                /*
                 * check if current node is the one 
                 */
                if(xmlStrcmp(nextChild->name, (const xmlChar *) nodeName) ==
                   0) {
                    // _VERBOSE2 printf(" found...\n");
                    resultNode = nextChild;
                }
                else {
                    resultNode = get_xml_node(nodeName, doc, nextChild);
                }
            }
        }
    }
    if(resultNode == NULL) {
    
        _VERBOSE2 printf("Node \"%s\" not found in \"%s\"...\n", nodeName, 
                            node->name);
        return NULL;
    }
    else {
        // _VERBOSE6 printf("found in \"%s\"...\n", node->name);
        return (xmlNodePtr) (resultNode);
    }
}


/**
 * parse commandline arguments
 */
void prefs_parse_arguments(int argc, char *argv[])
{
    static struct option cmdline_options[] = {
        {"help", 0, 0, 'h'},
        {"persistant", 0, 0, 'p'},
        {"verbose", 1, 0, 'v'},
        {"version", 0, 0, 'V'},
        {0, 0, 0, 0}
    };
    int cmdline_argument_index = 0;
    int cmdline_argument;

    _VERBOSE1 printf("%s()\n", __func__);
    
    while (1) {
        cmdline_argument =
            getopt_long(argc, argv, "-hpvV", cmdline_options,
                        &cmdline_argument_index);
        if(cmdline_argument == -1)
            break;

        switch (cmdline_argument) 
        {
            /* Version string */
            case 'V':
                printf("%s v%s-%s (Build-date: %s)\n",
                        PACKAGE, VERSION, REVISION, BUILDDATE);
                break;
            
                /*
                 * increase verbosity 
                 */
            case 'v':
                prefs_set_verbose(prefs_get_verbose()+1);
                _VERBOSE1 printf("%s(): verbosity level %d\n", 
                                __func__, prefs_get_verbose());
                break;
    
                /*
                 * user wants no daemon 
                 */
            case 'p':
                prefs.persistent = FALSE;
                _VERBOSE1 printf("** Don't detaching from terminal.\n");
                break;
    
                /*
                 * print help message 
                 */
            case 'h':
                u_print_help(argv[0]);
                break;
    
                /*
                 * eek! unrecognized cmdline option 
                 */
            default:
                break;
        }
    }
}

/**
 * initialize preferences module
 */
int prefs_init()
{
    /* clear local structure */
    memset(&prefs, 0, sizeof(struct Prefs));    
    return 0;
}

/**
 * initialize config-file
 */
int prefs_config_init()
{
    xmlNode *tmp_node;
    char *home_dir;
    
    
    _VERBOSE1 printf("%s(): \"%s\"\n", __func__, prefs.xml_filename);

        
    /* build prefs-filename */
    if(!(prefs.xml_filename = calloc(1, 255))) {
        printf("Not enough memory...\n");
        return -1;
    }
    
    if(!(home_dir = getenv("HOME"))) {
        printf("$HOME not set... Where is the config-file?\n");
        free(prefs.xml_filename);
        return -1;
    }

    snprintf(prefs.xml_filename, 255, "%s/.lasertraq/config.xml", home_dir);

   
    
    /*
     * new xml-parser 
     */
    if((prefs.xml_parser = xmlNewParserCtxt())) {
        /*
         * parse xml-file 
         */
        if(prefs.xml_filename) 
        {
            
            if((prefs.xml_doc =
                xmlCtxtReadFile(prefs.xml_parser,
                                prefs.xml_filename, NULL,
                                XML_PARSE_DTDVALID |
                                XML_PARSE_DTDLOAD | XML_PARSE_DTDATTR)))
            {
                /*
                 * check for validity 
                 */
                if(prefs.xml_parser->valid) {

                    /*
                     * get root-node 
                     */
                    if((prefs.root_node =
                        xmlDocGetRootElement(prefs.xml_doc)))
                    {
                        /*
                         * walk through all video-sources 
                         */
                        for(tmp_node =
                            prefs.root_node->children; tmp_node;
                            tmp_node = tmp_node->next) {
                                
                            /*
                             * got a node? 
                             */
                            if(tmp_node->type == XML_ELEMENT_NODE) {
                                _VERBOSE4 printf("xml_walk(): node \"%s\"\n",
                                                 tmp_node->name);

                                /*
                                 * video-source node? 
                                 */
                                if(xmlStrcmp
                                   (tmp_node->name,
                                    (xmlChar *) "video-source") == 0) {
                                        
                                    /*
                                     * append source to chain 
                                     */
                                    src_init_from_xml(tmp_node);
                                }
                            }
                        }
                    }
                    else {
                        _ERROR printf
                            ("init_config(): couldn't find root-node in \"%s\"\n",
                             prefs.xml_filename);
                        return -1;
                    }
                }
                else 
                {
                    _ERROR
                        printf
                        ("init_config(): config-file did not pass validation.\n");
                    return -1;
                }
            }
            else {
                _ERROR printf("init_config(): error parsing \"%s\"\n",
                              prefs.xml_filename);
                return -1;
            }
        }
        else {
            _ERROR printf
                ("init_config(): xml-filename is NULL. Please contact developer.\n");
            return -1;
        }
    }
    else {
        _ERROR printf("init_config(): failed to create xml-context.\n");
        return -1;
    }
    
    return 0;
}


/**
 * cleanup preferences module
 */
void prefs_cleanup()
{
    
    _VERBOSE1 printf("%s()\n", __func__);
    
    /*
     * free stuff 
     */
    free(prefs.xml_filename);
    if(prefs.xml_parser)
        xmlFreeParserCtxt(prefs.xml_parser);
    if(prefs.xml_doc)
        xmlFreeDoc(prefs.xml_doc);
}

/** 
 * @} 
 */
