/*
 * =====================================================================================
 * 
 *        Filename:  mposd.cpp
 * 
 *     Description:  A OSD display for MPD.
 * 
 *         Version:  1.0
 *         Created:  10/12/04 12:47:56 EDT
 *        Revision:  none
 *        Compiler:  g++
 * 
 *          Author:   (Natan Zohar), nzohar1ATbinghamtonDOTedu
 *         Company:  
 * 
 * =====================================================================================
 */

/* This is a very basic client for mpd which uses xosd to display the currently playing song on screen, 
 * the option parsing is also very limited and alot of work needs to be done on it. Also, Jethro Tull is 
 * the best music to code to. Ever.
 */

#include <ctime>
#include <cstdlib>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <sys/select.h>
#include <getopt.h>
#include <xosd.h>
#include "libmpdclient.h"

#define VERSION "0.0.1"

using namespace std;


// converts from type T to string
template<class T>
string toStr(T val) {
    stringstream ss;
    ss << val;
    return ss.str();
}

int write_to_stderr(string message) {
    write(2, message.c_str(), message.length());
    return 0;
}

int write_to_file(string message, string some_file, bool to_stdout) {
    if (!to_stdout) {
        ofstream outfile_writer(some_file.c_str(), ios::app);
        if (outfile_writer.fail()) {
            write_to_stderr("Couldn't open file for writing");
        } else {
            outfile_writer << message;
        }
        outfile_writer.close();
    } else {
        cout << message;
    }
    return 0;
}

string display_help() {
    return "mposd " + string(VERSION) + "\nUsage: mposd [OPTION] ... \n\n \
        -v, --version           display version\n \
        -h, --help              display this message\n\n \
        \
        Need to finish writing this.";
}

int main(int argc, char **argv) {
    string outfile;
    bool to_stdout = true;
    if (argc > 1) {
        outfile = argv[1];
        to_stdout = false; 
    }

    time_t local_time;
    
    mpd_Status *mpd_status;
    mpd_Connection *my_mpd;
    mpd_Song *mpd_song;
    mpd_InfoEntity *mpd_info_entity;
    int cur_song_id = -1,read_song_id;
    long cur_playlist_version = -1, read_playlist_version;
    string host = "localhost";
    int port = 6600;

    string disp_text; // string to keep sending to XOSD
    string artist = "", title = "", status = "";
    string read_status;
    bool bool_display_song = true;

    int seconds = 3;
    struct timeval *poll_timeout = new struct timeval;

    
    // OPTION PARSING
    
    poll_timeout->tv_sec = seconds;
    poll_timeout->tv_usec = 0;    
    
    // connect to mpd
    my_mpd = mpd_newConnection(host.c_str(), port, 10);
    if (my_mpd->error) {
        cerr << "Error in connecting to mpd at " << host << ":" << port << endl;
        exit(-1);
    }
    
    while (true) {
        mpd_sendCommandListOkBegin(my_mpd);
        mpd_sendStatusCommand(my_mpd);
        mpd_sendCurrentSongCommand(my_mpd);
        mpd_sendCommandListEnd(my_mpd);
        mpd_status = mpd_getStatus(my_mpd);
        mpd_nextListOkCommand(my_mpd);
        mpd_info_entity = mpd_getNextInfoEntity(my_mpd);
        mpd_finishCommand(my_mpd);
        if (mpd_info_entity == NULL) {
            write_to_stderr("No Song is selected\n");
        } else {
            mpd_song = mpd_info_entity->info.song;
            read_song_id = mpd_status->song;

            if (cur_song_id != read_song_id || cur_playlist_version != read_playlist_version) {
                bool_display_song = true;
                artist = mpd_song->artist;
                title = mpd_song->title;
                cur_song_id = read_song_id;
                cur_playlist_version = read_playlist_version;
            }

            if (bool_display_song) {
                disp_text = artist + " - " + title;
                time(&local_time);
                disp_text = disp_text + " * " + ctime(&local_time);
                write_to_file(disp_text, outfile, to_stdout);
                bool_display_song = false;
            }

        }
        poll_timeout->tv_sec = seconds; // make it wait another set of seconds, since select changes the timeout val
        select(0, NULL, NULL, NULL, poll_timeout);
    }
    
}
