/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#+
#+     Internet Radio Automation & Encoding Toolkit
#+
#+     Copyright (C) 2018 - 2026 by Kevin C. O'Kane
#+
#+     Kevin C. O'Kane
#+     kc.okane@gmail.com
#+     https://www.cs.uni.edu/~okane
#+     https://threadsafebooks.com/
#+
#+ This program is free software; you can redistribute it and/or modify
#+ it under the terms of the GNU General Public License as published by
#+ the Free Software Foundation; either version 2 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 General Public License for more details.
#+
#+ You should have received a copy of the GNU General Public License
#+ along with this program; if not, write to the Free Software
#+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#+
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/

//      July 13, 2026

#include "includes.h"
#include "common-externs.h"

#define SLASH '/'

//----------------------------------------------
//	Main Timer
//----------------------------------------------

gboolean	timer_handler(struct APW *widgets) {

//--------------------------------------------------
//	enter critical section
//	only one thred at a time allowed to enter
//--------------------------------------------------

	gdk_threads_enter();

	gint x,y;
	char cmd[1024];
	char cmd1[1024];
	int i,j;
	char tmp[1024],dmy[64];
	double Lmax =0.0,  Rmax = 0.0;

//--------------------------------
//	media time scan running?
//--------------------------------

	if (scan_in_progress) {
		gdk_threads_leave();
		return TRUE;
		}

	if (firstTime) { // first time the timer entered

		firstTime = 0; // don't do this again

		GdkColor color; // background color Top1
		color.red   = 0x2222;
		color.green = 0x2222;
		color.blue  = 0x4444;
		gtk_widget_modify_bg(TopBG, GTK_STATE_NORMAL, &color);

		gtk_toggle_button_set_active (
			GTK_TOGGLE_BUTTON(displayBars), TRUE); // default audio show
		gtk_spin_button_set_value (GTK_SPIN_BUTTON(barWidth), 4.0);

		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(above_bars)))
			super_bars = 1;
		else super_bars = 0;

		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(connectGraph)))
			connect_graph = 1;
		else connect_graph = 0;

		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(randColors)))
			rand_colors = 1;
		else rand_colors = 0;

		if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(displayBars)))
			display_bars = 1;
		else display_bars = 0;

		on_mini_mode_toggled(mini_mode);

		updateTimes(); // on tiles

		SP->volumeLevel = INIT_VOLUME; // starting preamp volume
		outVolume(INIT_VOLUME);

		MaxAudioSample = 0; // permit AGC to raise gain if AGC on

		gtk_widget_queue_draw (video_draw);

		gtk_stack_set_visible_child (GTK_STACK(stack1), web_panel);
		gtk_widget_show(webkit);

		strcpy(tmp, "https://www.cs.uni.edu/~okane/pocketradio.html");

		gtk_entry_set_text (GTK_ENTRY(web_entry), Web_Page);
		while (gtk_events_pending ()) gtk_main_iteration ();

		webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webkit), Web_Page);
		webkit_web_view_reload_bypass_cache(WEBKIT_WEB_VIEW(webkit));

		gtk_widget_set_size_request (webkit, 580, 550);
		while (gtk_events_pending ()) gtk_main_iteration ();
//	gtk_stack_set_visible_child (GTK_STACK(stack1), ed_fixed);
//	on_scan_media_clicked(NULL);
		LoadProgram(Program_List);

		} // done with first time only code

	if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(displayBars)) &&
	        !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(connectGraph)))
		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(displayBars), TRUE);

//---------------------------------------------------
//	update playlist slider and gain label colors
//---------------------------------------------------

	/********* auto disable bars if sprinkles and damp set
	        if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sprinkleDamp)) &&
	            gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(traces)))

	        	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(displayBars)))
	        		gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(displayBars), FALSE);
	*********/


	if (vlc_playing()) {
		update_vlcPosition(); // slider
		}
	else {
		gtk_widget_show(video_bg);
		gtk_widget_hide(video_draw);
		gtk_widget_hide(drawV);
		gtk_adjustment_set_value (GTK_ADJUSTMENT(adjustment8), 0); // position slider
		timeRemaining = 0;
		strcpy(SP->CurrentPlay, "");
//                if (SP->playProgram == 0 ) vlc_stop();
		}

		{
		char tmp[100];
		sprintf(tmp,"AGC %3.1f ", SP->volumeLevel-100.);
		gtk_label_set_text(GTK_LABEL(agc_gain), tmp);
		}

	if (MaxAudioSample) { // max agc1 achieved
		GdkColor color; // default background color
		color.red   = 0xffff;
		color.green = 0x0000;
		color.blue  = 0x0000;
		gtk_widget_modify_bg(agcLbl1, GTK_STATE_NORMAL, &color);
		gtk_widget_modify_bg(agc_gain, GTK_STATE_NORMAL, &color);
		color.red   = 0x0000;
		color.green = 0x0000;
		color.blue  = 0x0000;
		gtk_widget_modify_bg(agcLbl2, GTK_STATE_NORMAL, &color);
		}
	else {
		GdkColor color; // default background color
		color.red   = 0x0000;
		color.green = 0x0000;
		color.blue  = 0x0000;
		gtk_widget_modify_bg(agc_gain, GTK_STATE_NORMAL, &color);
		gtk_widget_modify_bg(agcLbl1, GTK_STATE_NORMAL, &color);
		}

//	if (! vlc_playing()) // hide movie panel

	if (SP->skipCurrent) { // skip
		SP->skipCurrent = 0;
		vlc_stop();  // will be restarted with new file if in program mode
		}

	if (SP->skip) { // skip++
		SP->skip = 0;
		findNext(); // function will mark next in line as played
		}

//------------------------------------
//      Program mode management
//	SP->Pause 	pause at end
//	SP_>VlcPauseFlg	player paused
//------------------------------------

	if (SP->playProgram) {
		gtk_widget_show(programMode);   // 'Auto' label visibility
		gtk_widget_show(programMode1);  // 'Auto' label visibility
		}
	else {
		gtk_widget_hide(programMode);
		gtk_widget_hide(programMode1);
		}

	if (SP->playProgram && !SP->Pause) { // advance to next file?

		gtk_widget_show(nextPlay); // show cueued file label text

		if (! SP->VlcPauseFlg && ! vlc_playing()) { // advance to next

			if ( (SP->NowPlaying = nextSelection() ) < 0) {
				SP->playProgram = 0;		// no more to play - exit mode
				gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(pauseAtEnd), FALSE);
				gtk_widget_hide(programMode);	// we're done - not in program mode
				gtk_widget_hide(programMode1);	// we're done - not in program mode
				}

			else {
				printf("timer says play: %s\n",SP->playThis);
				vlc_start(); // play it, Sam
				}
			}
		}

	if (!SP->playProgram) { // not program mode

		gtk_widget_hide(nextPlay); // show cueued file label text

		if (SP->playClip) { // play single file
			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(pauseAtEnd), FALSE);
			SP->skipCurrent = 0;
			SP->playClip = 0;
			ClearPlayers();
			vlc_start();
			}
		}

	if (!SP->VlcPauseFlg && vlc_playing()) { // player playing

		for (i=0; i<10; i++) { // past 10 ticks of data from buffer
			if (rchan[i] > Rmax) Rmax = rchan[i]; // find max
			if (lchan[i] > Lmax) Lmax = lchan[i]; // find max
			}

		L_Clipping = R_Clipping = 0;

		if (Lmax > ClipLevel) L_Clipping = 1;
		if (Rmax > ClipLevel) R_Clipping = 1;
		if (Lmax > Rmax) curLevel = Lmax;
		else curLevel = Rmax;
		agc_adjust();
		}

//------------------------------
//	set time of day string
//------------------------------

	struct tm *tod;
	time_t tx = time(NULL);         // get normal time of day
	tod = localtime(&tx);           // get time structure pointer

	strcpy(time_string, asctime(tod));      // ASCII string of time
	time_string[strlen(time_string)-1] = 0; // char at end
	gtk_label_set_text(GTK_LABEL(time_of_day), time_string);

//--------------------------------------------------------
//	used by graphical clock - not used at the moment
//--------------------------------------------------------

	second = tod->tm_sec;           // extract seconds
	minute = tod->tm_min;           // extract minutes
	hour = tod->tm_hour % 12;       // extract hour (12)

	time_t t = time(0); // unix time
	struct tm *T = localtime(&t);

//-------------------------------------------------------------------
//	time until top of hour
//-------------------------------------------------------------------

	int until = 60 - T->tm_min;
	sprintf(tmp,"Top of Hour: %d min", until);
	gtk_label_set_text(GTK_LABEL(widgets->TimeToHour), tmp);

	updateTimes(); // update tiles

//-----------------------------------------------
//	show and decrement play clock as needed
//-----------------------------------------------

	time_t t1, t2;

	if (vlc_playing()) {  // player times
		t1 = libvlc_media_player_get_time(mediaPlayer) / 1000;    // amount played
		t2 = libvlc_media_player_get_length(mediaPlayer) / 1000;  // duration
		}
	else  {
		t1 = t2 = 0;
		gtk_label_set_text(GTK_LABEL(posLbl), " 0.0%");    // update label
		}

	timeRemaining = t2 - t1;

//-----------------------------------------------
//	update time remaining label "... in xxx"
//-----------------------------------------------

	if (timeRemaining > 0) {
		sprintf(dmy, "in %d secs", timeRemaining);
		gtk_label_set_text(GTK_LABEL(widgets->timer), dmy);    // update label
		}

	else gtk_label_set_text(GTK_LABEL(widgets->timer), "");    // update label

//---------------------------------------------------------------------
//	update label showing time of day when next file can be played
//---------------------------------------------------------------------

	time_t tn;

	tn = time(0);
	tn = tn + timeRemaining;

//---------------------------------------
//	last dmy updated is the result
//---------------------------------------

	sscanf(ctime(&tn),"%s %s %s %s ",dmy,dmy,dmy,dmy);

	strcpy(SP->TimeNext, "Cue: ");
	strcat(SP->TimeNext, dmy); // last value from above is time of day

	gtk_label_set_text(GTK_LABEL(widgets->timeNext), SP->TimeNext);    // update label

//------------------------------------------------------
//	reload main panel title text //	every 5 seconds
//------------------------------------------------------

	if (t % 5 == 0) {
		char tmp[2048];
		sprintf(tmp, "%s/title.txt", Code_Home);
		FILE *s1 = fopen(tmp, "r");
		if (s1) {
			fgets(tmp, 100, s1);
			tmp[strlen(tmp)-1] = 0;
			gtk_label_set_text(GTK_LABEL(sgrStudio), tmp); // overwrites default title
			fclose(s1);
			}
		}

//--------------------------------------------
//	display queued selection
//--------------------------------------------

	if (SP->playProgram) {

		if (findNext1() >= 0) { // find but don't don't mark item as played
			strcpy(tmp, SP->next_random);
			i = strlen(tmp) - 4;
			if (tmp[i] == '.' || tmp[i-1] == '.') tmp[i] = 0;
			tmp[85] = 0; // short form displayed
			gtk_label_set_text(GTK_LABEL(widgets->nextPlay), tmp);
			}

		else {
			strcpy(tmp, "Cue:"); // none - no more to play
			gtk_label_set_text(GTK_LABEL(widgets->nextPlay), tmp);
			}
		}

	if (strlen(SP->CurrentPlay)) { // update currently playing
		strcpy(tmp, SP->CurrentPlay);

		for (i = strlen(tmp); i > 0; i--)
			if (tmp[i] == '.') {
				tmp[i] = 0;
				for (j = i; j > 0; j--)
					if (tmp[j] == '/') {
						j++;
						break;
						}
				break;
				}

		tmp[j + 85] = 0; // short form displayed
		gtk_label_set_text(GTK_LABEL(widgets->currentFile), &tmp[j]);
		}

	static int lastPlaying = -1;

//------------------------------------------------------------------------------------
//	is something playing and is it different than the last time we were here?
//------------------------------------------------------------------------------------

	if ( 0 && SP->NowPlaying != -1 && SP->NowPlaying != lastPlaying) {

		lastPlaying = SP->NowPlaying;

		programPlayed[SP->NowPlaying]++; // nbr times played

//--------------------------------------------------------------
//		re-display current in middle / half page
//		if no_move, tials do not rearrange
//--------------------------------------------------------------

		if (! no_move) {
			if (reCenter)
				SP->begin = SP->NowPlaying - 6;
			else
//-----------------------------------------------------------------------------------
//			re-display program buttons with current at beginning
//-----------------------------------------------------------------------------------
				SP->begin = SP->NowPlaying;

			if (SP->begin < 0) SP->begin = 0; // beginning of array
			}

		DisplayProgramButtons();  // repaint program display

		}

	gdk_threads_leave();
	return TRUE; // come back, please
	}

