/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#+
#+     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 3, 2026

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

#include <vlc/libvlc.h>
#include <vlc/libvlc_renderer_discoverer.h>
#include <vlc/libvlc_media.h>
#include <vlc/libvlc_media_player.h>

#define SLASH '/'

//-------------------------------------
//	simple join - no transition
//-------------------------------------

void	on_join_videos_clicked(GtkWidget *w) {

	char tmp[16000], new[16000];
	int i, pcount = 0;

	close_boxes(); // hide box and stuff

	join_button_clicked();

	new_name(new, "join.mp4", "join");

	if (SP->scount < 1) return;

	FILE *f1 = fopen("lst.txt", "w");

	for (i = 0; i< SP->scount; i++) {
		pcount++;
		if (programData[i]->play) {

			if (filetype(ProgramArray[i]) == URL) {
				error_message("Files must be local to be joined.", NULL);
				return;
				}

			fprintf(f1, "file \'%s\'\n", ProgramArray[i]);
			};
		}

	fclose(f1);

	if (!pcount) {
		error_message("No files selected.", NULL);
		return;
		}

	time_t tmark = time(0);

	sprintf(tmp,
	        "ffmpeg -y " FFLOGLEVEL " -f concat -safe 0 -i lst.txt -c copy \"%s\"",
	        new);

	int ierr = ff_run("joiner",tmp, -1);

	if (ierr != 0) {
		error_message("There were errors or interupts processing", tmp);
		sprintf(tmp, "rm %s\n", new);
		system(tmp);
		return;
		}

	sprintf(tmp, "%s created\n", new);

	clear_play();

	on_scan_video_dir_clicked(UPDATE_TILES);
        DisplayProgramButtons();

	system("rm lst.txt");
	printf("rm lst.txt\n");

	}


//-----------------------------
//	join with transition
//-----------------------------

void	on_join_wipeleft_clicked(GtkWidget *w) {
	join_fade_clicked("lft", WIPE_LEFT);
	}

void	on_join_circleclose_clicked(GtkWidget *w) {
	join_fade_clicked("cir", CIRCLE_CLOSE);
	}


void	on_join_dissolve_clicked(GtkWidget *w) {
	join_fade_clicked("dis", DISSOLVE);
	}

void	on_slideleft_clicked(GtkWidget *w) {
	join_fade_clicked("sll", SLIDELEFT);
	}

void	on_pixelize_clicked(GtkWidget *w) {
	join_fade_clicked("pxl", PIXELIZE);
	}

void	on_circlecrop_clicked(GtkWidget *w) {
	join_fade_clicked("ccr", CIRCLECROP);
	}

void	on_wipeup_clicked(GtkWidget *w) {
	join_fade_clicked("wup", WIPEUP);
	}

void	on_slideup_clicked(GtkWidget *w) {
	join_fade_clicked("sup", SLIDEUP);
	}

void	on_wiperight_clicked(GtkWidget *w) {
	join_fade_clicked("wrt", WIPERIGHT);
	}

void	on_slideright_clicked(GtkWidget *w) {
	join_fade_clicked("srt", SLIDERIGHT);
	}

void	on_wipedown_clicked(GtkWidget *w) {
	join_fade_clicked("wdn", WIPEDOWN);
	}

void	on_rantran_clicked(GtkWidget *w) {
	int i = rand() % 19 + 1; // random 1 thru 19
	join_fade_clicked("rdm", RANDOMTRAN);
	}

void	on_slide_down_clicked(GtkWidget *w) {
	join_fade_clicked("sld", SLIDE_DOWN);
	}

void	on_horzopen_clicked(GtkWidget *w) {
	join_fade_clicked("hop", HORZOPEN);
	}

void	on_fade_clicked(GtkWidget *w) {
	join_fade_clicked("fad", FADE);
	}

void	on_vertopen_clicked(GtkWidget *w) {
	join_fade_clicked("vop", VERTOPEN);
	}

void	on_radial_wipe_clicked(GtkWidget *w) {
	join_fade_clicked("rad", RADIAL_WIPE);
	}

void	on_squeezeh_clicked(GtkWidget *w) {
	join_fade_clicked("sqh", SQUEEZEH);
	}

void	on_squeezev_clicked(GtkWidget *w) {
	join_fade_clicked("sqv", SQUEEZEV);
	}

void	on_wipebr_clicked(GtkWidget *w) {
	join_fade_clicked("wbr", WIPEBR);
	}




//-------------------------------------
//	join with transition clicked
//-------------------------------------

void	join_fade_clicked(char *style, int type) {

//------------------------------------------
//	style is string code for join type
//	type is define code for join type
//------------------------------------------

	char tmp[16000], filename[MAX_FILE_NAME];
	char result[16000];
	char out_filename[16000];
	char mhd_name[16000];
	int i, j, k, pcount = 0;

	join_button_clicked(); // pause vlc
	
	time_t begin_time = time(NULL);

	for (i = 0; i < (SP->scount); i++) { // count and remember first
		if (programData[i]->play) {

			if (filetype(ProgramArray[i]) == URL) {
				error_message("Files must be local to be joined.", NULL);
				return;
				}

			pcount++;
			if (pcount == 1) { // note first
				j = i;
				} // continue counting
			}
		}

	if (pcount < 2) {
		error_message("Too few files selected.", NULL);
		return;
		}

	vid_fmt_std(result, ProgramArray[j], out_filename, "join");

	strcpy(filename, "join-");
	strcat(filename, style);
	strcat(filename, ".mp4");

	sprintf(tmp, "rm -f %s ", mhd_ref(filename, mhd_name));
	ff_run("Remove old copy", tmp, -1);

	sprintf(tmp, "rm -f %s ", mhd_ref("jointmp.mp4", mhd_name));
	ff_run("Remove tmp", tmp, -1);

//---------------------------
//	main join loop
//---------------------------

	pcount = 0;

	for (i = 0; i < (SP->scount); i++) {
		if (programData[i]->play) {
			programData[i]->play = 0;
			int err = wipe(filename, ProgramArray[i], style, type); // join files
			if (err < 0) return;
			}
		}

	sprintf(tmp, "cp \"%s\" \"%s\"", filename, out_filename);
	ff_run("Copy1:", tmp, -1);

	sprintf(tmp, "rm -f %s ", mhd_ref(filename, mhd_name));
	ff_run("Remove", tmp, -1);

	sprintf(tmp, "rm -f %s ", mhd_ref("jointmp.mp4", mhd_name));
	ff_run("Remove", tmp, -1);

	clear_play();

	addToTop(filename); // starter join file

	programData[0]->play = 1;

        sprintf(tmp, "*** total join time: %d seconds.\n", time(NULL) - begin_time);
        printf(tmp);
        Zippy_says(tmp);

	return;
	}

//-----------------------------------------
//	ffmpeg esetup for join with fade
//-----------------------------------------

int	wipe(char *first, char *xsecond, char *style, int type) {

	char second[8192];
	strcpy(second, xsecond);
	char mhd_name[16000];
	char tmp[16000];

//------------------------------------
//	is second file a still image?
//	convert to video
//------------------------------------

	int ft = filetype(second);

	if (ft == JPG || ft == PNG ) {

		char result[2048], filename[8192], tmp[16000];

		vid_fmt_std(result, second, filename, "stl");

		int err_stat;

		clip_duration = gtk_spin_button_get_value(GTK_SPIN_BUTTON(clip_duration_spinner));

		sprintf(tmp, "ffmpeg -y " FFLOGLEVEL " -f lavfi "
		        "-i anullsrc=channel_layout=stereo:sample_rate=44100 "
		        "-loop 1 -i \"%s\" "
		        "-c:v libx264 -t %d -vf fps=25 -pix_fmt yuva420p  "
		        "-c:a aac -map 0:a -map 1:v "
		        " %s  -c:a libmp3lame -b:a 128k -c:v libx264 -preset veryslow -crf 20  %s ",

		        second, clip_duration, result, mhd_ref("jointmp.mp4", mhd_name));

		err_stat = ff_run("***Still", tmp, -1);
		}

	else {

//-------------------------------------------------------
//      first file is a video clip
//      copy initial file to output file as initial clip
//-------------------------------------------------------

		char result[2048], xfilename[8192], tmp[16000];

		vid_fmt_std(result, second, xfilename, "scl");

		sprintf(tmp, "ffmpeg -y " FFLOGLEVEL " -i \"%s\" "
		        " %s "
		        " -c:a libmp3lame -b:a 128k -c:v libx264 -preset veryslow -crf 20 %s" ,
		        second, result, mhd_ref("jointmp.mp4", mhd_name));

		int err_stat = ff_run("Video", tmp, -1);
		}

	if (! file_exists(first) ) {
		char tmp1[16000];
		sprintf(tmp, "cp %s \"%s\"", mhd_ref("jointmp.mp4", tmp1), mhd_ref(first, mhd_name));
		int err_stat = ff_run("Copy2:", tmp, -1);
		return 0;
		}

//------------------------
//	length in seconds
//------------------------

	double len = GetTime(first);

	len = len - trans_duration;

	char ffop[32];

//-------------------------------------------------------------
//	https://trac.ffmpeg.org/wiki/FancyFilteringExamples
//-------------------------------------------------------------

	if (type == RANDOMTRAN)
		type = rand() % 19 + 1; // random 1 thru 19

	if (type == WIPE_LEFT) strcpy(ffop, "wipeleft");
	else if (type == CIRCLE_CLOSE) strcpy(ffop, "circleclose");
	else if (type == DISSOLVE) strcpy(ffop, "dissolve");
	else if (type == SLIDE_DOWN) strcpy(ffop, "slidedown");
	else if (type == RADIAL_WIPE) strcpy(ffop, "radial");
	else if (type == WIPEBR) strcpy(ffop, "wipebr");
	else if (type == CIRCLECROP) strcpy(ffop, "circlecrop");
	else if (type == PIXELIZE) strcpy(ffop, "pixelize");
	else if (type == SLIDELEFT) strcpy(ffop, "slideleft");
	else if (type == WIPEDOWN) strcpy(ffop, "wipedown");
	else if (type == WIPEUP) strcpy(ffop, "wipeup");
	else if (type == SLIDEUP) strcpy(ffop, "slideup");
	else if (type == SLIDERIGHT) strcpy(ffop, "slideright");
	else if (type == WIPERIGHT) strcpy(ffop, "wiperight");
	else if (type == VERTOPEN) strcpy(ffop, "vertopen");
	else if (type == HORZOPEN) strcpy(ffop, "horzopen");
	else if (type == SQUEEZEH) strcpy(ffop, "squeezeh");
	else if (type == SQUEEZEV) strcpy(ffop, "squeezev");
	else if (type == FADE) strcpy(ffop, "fade");
	else strcpy(ffop, "wipeleft"); // default

//	strcat(ffop, "\n");

	printf("Joining %s to \n%s\n", first, second);

	char tmp1[16000];

	sprintf(tmp,
	        "ffmpeg -y " FFLOGLEVEL " -i %s -i \"%s\" "
	        "-filter_complex "
	        "\"[0v][1v]xfade=transition=%s:duration=%d:offset=%f,format=yuv420p[video];"
	        "[0:a][1:a]acrossfade=d=%d:c1=tri:c2=tri[audio]; [video]fps=25[video1]\" "
	        " -map \"[video1]\" -map \"[audio]\" -movflags +faststart  -c:a libmp3lame -b:a 128k -c:v libx264 -preset veryslow -crf 20  \"%s\" ",

	        mhd_ref(first, tmp1), mhd_ref("jointmp.mp4", mhd_name), ffop,
	        trans_duration, len,
	        trans_duration, "tmp.mp4");

	int err = ff_run(ffop, tmp, -1);

	if (err != 0) {
		error_message("There were problems or interrupts processing", tmp);
		system("rm -f tmp.mp4");
		clear_play();
		return -1;
		}

	sprintf(tmp, "rm \"%s\" && mv tmp.mp4 \"%s\"", first, first);
	printf("%s\n", tmp);
	system(tmp);

	return 0;

	}

void    join_button_clicked() { // ok button substitute

	vlc_pause();

	}

