#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
#include <Xm/Label.h>
#include <Xm/PushB.h>
#include <Xm/ToggleB.h>
#include <Xm/MainW.h>
#include <Xm/List.h>
#include <Xm/Form.h>
#include <Xm/RowColumn.h>
#include <Xm/Separator.h>
#include <Xm/Frame.h>
#include <Xm/ScrollBar.h>

#include "tuner.h"

#define LABEL(args, n, name, parent) \
  XtCreateManagedWidget(name, xmLabelWidgetClass, parent, NULL, 0)

static void cb_tuner(), cb_mute(), cb_details(), cb_revert(), cb_ok(),
  cb_playlist(), cb_radio();
#ifdef ANP_COMMAND
static void cb_anp();
#endif /* ANP_COMMAND */
#ifdef VOLUME
static void cb_volume();
#endif /* VOLUME */

int ui_active = 0;
char *kept_message;		/* Message to be displayed after init */

int tuner_pos = 0, prev_pos = 0;

void
init_ui(argcp, argv)
    int *argcp;
    char **argv;
{
    Arg args[20];
    int n = 0;
    XmString str1;
    char str[100];
    int i;

    ui_active = 1;

    toplevel = XtInitialize(argv[0], "Tuner", NULL, 0, argcp, argv);

    n = 0;
    form = XtCreateManagedWidget("form", xmFormWidgetClass,
				toplevel, args, n);

    labelCurrent = LABEL(args, n, "labelCurrent", form);

    n = 0;
    currentStation = XtCreateManagedWidget("stationF", xmFrameWidgetClass,
					   form, args, n);
    
    n = 0;
    currentStation = XtCreateManagedWidget("station", xmLabelWidgetClass,
					   currentStation, args, n);

    (void)LABEL(args, n, "labelCurPlaying", form);

    n = 0;
    currentPlaying = XtCreateManagedWidget("playingF", xmFrameWidgetClass,
					   form, args, n);
    
    n = 0;
    currentPlaying = XtCreateManagedWidget("playing", xmLabelWidgetClass,
					   currentPlaying, args, n);

    (void)LABEL(args, n, "labelCurTime", form);

    n = 0;
    currentTime = XtCreateManagedWidget("timeF", xmFrameWidgetClass,
					   form, args, n);
    
    n = 0;
    currentTime = XtCreateManagedWidget("time", xmLabelWidgetClass,
					currentTime, args, n);
    
    labelPlaylist = LABEL(args, n, "labelPlaylist", form);
    
    n = 0;
    playlistBrowser = XmCreateScrolledList(form, "playlist", args, n);
    XtAddCallback(playlistBrowser, XmNbrowseSelectionCallback, cb_playlist, 0);
    XtManageChild(playlistBrowser);

    labelTuner = LABEL(args, n, "labelTuner", form);

    n = 0;
    tunerBrowser = XmCreateScrolledList(form, "tuner", args, n);
    XtAddCallback(tunerBrowser, XmNbrowseSelectionCallback, cb_tuner, 0);
    XtManageChild(tunerBrowser);

#ifdef VOLUME

    labelVolume = LABEL(args, n, "labelVolume", form);
    
    n = 0;
    volumeSlider = XtCreateManagedWidget("volume", xmScrollBarWidgetClass,
				       form, args, n);
    XtAddCallback(volumeSlider, XmNvalueChangedCallback, cb_volume, 0);
    XtAddCallback(volumeSlider, XmNdragCallback, cb_volume, 0);
    show_volume(getvolume());
#endif /* VOLUME */

    n = 0;
    muteButton = XtCreateManagedWidget("mute", xmToggleButtonWidgetClass,
				       form, args, n);
    XtAddCallback(muteButton, XmNvalueChangedCallback, cb_mute, 0);

    n = 0;
    revertButton = XtCreateManagedWidget("revert", xmPushButtonWidgetClass,
					 form, args, n);
    XtAddCallback(revertButton, XmNactivateCallback, cb_revert, 0);

    n = 0;
    okButton = XtCreateManagedWidget("OK", xmPushButtonWidgetClass,
				     form, args, n);
    XtAddCallback(okButton, XmNactivateCallback, cb_ok, 0);

#ifdef ANP_COMMAND
    n = 0;
    anpButton = XtCreateManagedWidget("anp", xmToggleButtonWidgetClass,
				       form, args, n);
    XtAddCallback(anpButton, XmNvalueChangedCallback, cb_anp, 0);
#endif /* ANP_COMMAND */

    n = 0;
    radioButton = XtCreateManagedWidget("radio", xmToggleButtonWidgetClass,
				     form, args, n);
    XtAddCallback(radioButton, XmNvalueChangedCallback, cb_radio, 0);
}

static void
cb_playlist(w, udata, wdata)
    Widget *w;
    XmListCallbackStruct *wdata;
    void *udata;
{
    XmListDeselectAllItems(playlistBrowser);
} 

static void
cb_tuner(w, udata, wdata)
    Widget *w;
    XmListCallbackStruct *wdata;
    void *udata;
{
    prev_pos = tuner_pos;
    tuner_pos = wdata->item_position;
    do_tune(tuner_pos);
} 

static void
cb_mute(w, udata, wdata)
    Widget *w;
    XmToggleButtonCallbackStruct *wdata;
    void *udata;
{
    do_mute(wdata->set);
}

static void
cb_details(w, udata, wdata)
    Widget *w;
    void *wdata;
    void *udata;
{
}

static void
cb_revert(w, udata, wdata)
    Widget *w;
    void *wdata;
    void *udata;
{
    int i;

    i = prev_pos;
    prev_pos = tuner_pos;
    tuner_pos = i;
    do_tune(tuner_pos);
}

static void
cb_ok(w, udata, wdata)
    Widget *w;
    void *wdata;
    void *udata;
{
    exit(0);
}

#ifdef ANP_COMMAND
int anp_pid = -1;
FILE *anp_fp;
XtInputId anp_id;

static void
cb_anpdone()
{
    do_mute(0);
    anp_pid = -1;
    pclose(anp_fp);
    XtRemoveInput(anp_id);
}

static void
cb_anp(w, udata, wdata)
    Widget *w;
    XmToggleButtonCallbackStruct *wdata;
    void *udata;
{
    char dbuf[10];
    char cmdbuf[1024];
    
    if ( wdata->set ) {
	if ( anp_pid > 0) {
	    fprintf(stderr, "tuner: anp already active\n");
	    return;
	}
	do_mute(1);
	sprintf(cmdbuf, "%s %s", ANP_COMMAND, COMMAND_TRAILER);
	if ( (anp_fp=popen(cmdbuf, "r")) == NULL ) {
	    perror(cmdbuf);
	    return;
	}
	if ( fgets(dbuf, 10, anp_fp) == NULL
	    			|| sscanf(dbuf, "%d", &anp_pid) != 1) {
	    fprintf(stderr, "tuner: anp command did not give pid\n");
	    fclose(anp_fp);
	    anp_pid = -1;
	    return;
	}
	anp_id = XtAddInput(fileno(anp_fp), XtInputReadMask, cb_anpdone, 0);
    } else {
	if ( anp_pid < 0 ) {
	    fprintf(stderr, "tuner: anp not active\n");
	    return;
	}
	if ( kill(anp_pid, SIGTERM) < 0 ) {
	    fprintf(stderr, "kill %d:", anp_pid);
	    perror("");
	}	
	cb_anpdone();
    }
}
#endif /* ANP_COMMAND */

static void
cb_radio(w, udata, wdata)
    Widget *w;
    XmToggleButtonCallbackStruct *wdata;
    void *udata;
{
    char cmdbuf[1024];

    if( wdata->set ) {
	sprintf(cmdbuf, "%s %s &", RADIO_COMMAND, COMMAND_TRAILER);
	system(cmdbuf);
#ifdef KILLRADIO_COMMAND
    } else {
	system(KILLRADIO_COMMAND);
#endif /* KILLRADIO_COMMAND */
    }
    sleep(2);
    do_curinfo();
}

#ifdef VOLUME
static void
cb_volume(w, udata, wdata)
    Widget *w;
    XmScrollBarCallbackStruct *wdata;
    void *udata;
{
    setvolume(wdata->value);
}

void
show_volume(value)
    int value;
{
    Arg args[2];
    int n;

    n = 0;
    XtSetArg(args[n], XmNvalue, value); n++;
    XtSetValues(volumeSlider, args, n);
}
#endif /* VOLUME */

/*
** show_tune - Show which station we're tuned to
*/
void
show_tune(station, name, playing, since, mute)
    int station;
    char *name, *playing, *since;
    int mute;
{
    Arg args[2];
    int n;
    XmString str;

    if ( !ui_active ) return;
    XmListDeselectAllItems(tunerBrowser);
    if ( station ) {
      XmListSelectPos(tunerBrowser, station, 0);
      if ( prev_pos == 0 )
	prev_pos = station;
  }

    n = 0;
    str = XmStringCreateLtoR(name, XmSTRING_DEFAULT_CHARSET);
    XtSetArg(args[n], XmNlabelString, str); n++;
    XtSetValues(currentStation, args, n);
    
    n = 0;
    str = XmStringCreateLtoR(playing, XmSTRING_DEFAULT_CHARSET);
    XtSetArg(args[n], XmNlabelString, str); n++;
    XtSetValues(currentPlaying, args, n);
    
    n = 0;
    str = XmStringCreateLtoR(since, XmSTRING_DEFAULT_CHARSET);
    XtSetArg(args[n], XmNlabelString, str); n++;
    XtSetValues(currentTime, args, n);

    n = 0;
    XtSetArg(args[n], XmNset, mute); n++;
    XtSetValues(muteButton, args, n);

    n = 0;
    XtSetArg(args[n], XmNset, (station != 0)); n++;
    XtSetValues(radioButton, args, n);
    
}

/*
** show_stations - Show new station list.
*/
static void
new_browser(browser, slist, nitems)
    Widget browser;
    char **slist;
    int nitems;
{
    XmString *list;
    int i;

    /* XXX Should we free old items here? */
    XmListDeselectAllItems(browser);
#ifndef MOTIF1_0
    XmListDeleteAllItems(browser);
#else
    {
	Arg args[1];
	XtSetArg(args[0], XmNitemCount, NULL);
	XtGetValues(browser, args, 1);
	for(i=0; i<(int)args[0].value; i++)
	  XmListDeletePos(browser, 1);
    }
#endif
    list = (XmString *)XtMalloc(sizeof(XmString)*nitems);
    for ( i=0; i<nitems; i++)
	list[i] = XmStringCreate(slist[i], XmSTRING_DEFAULT_CHARSET);
#ifdef MOTIF1_0
    for (i=0; i<nitems; i++)
      XmListAddItem(browser, list[i], i+1);
#else
    XmListAddItems(browser, list, nitems, 0);
#endif
    for ( i=0; i<nitems; i++) {
        XtFree(list[i]);

    }
    XtFree(list);
}

void
show_tuner(slist, nitems)
    char **slist;
    int nitems;
{
    if ( !ui_active ) return;
    new_browser(tunerBrowser, slist, nitems);
}

void
show_playlist(slist, nitems, col)
    char **slist;
    int nitems;
{
    static Arg arg[1];

    if ( !ui_active ) return;
    new_browser(playlistBrowser, slist, nitems);
    XmListSetBottomPos(playlistBrowser, 0);
    XtSetArg(arg[0], XmNforeground, 0);
    if ( col ) {
	XtGetValues(labelCurrent, arg, 1);
    } else {
	XtGetValues(labelTuner, arg, 1);
    }
    XtSetValues(labelPlaylist, arg, 1);
}

watch_socket(sock, cback)
    int sock;
    int (*cback)();
{
    (void)XtAddInput(sock, XtInputReadMask, cback, 0);
}
