#ifndef NK_IMPLEMENTATION
#include "nuklear_lib/nuklear.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#endif //!NK_IMPLEMENTATION

#include "ccextractorGUI.h"
#include "tabs.h"
#include "command_builder.h"

void command_builder(struct built_string *command,
		     struct main_tab *main_settings,
		     struct network_popup *network_settings, struct input_tab *input,
		     struct advanced_input_tab *advanced_input,
		     struct output_tab *output,
		     struct decoders_tab *decoders,
		     struct credits_tab *credits,
		     struct debug_tab *debug,
		     struct burned_subs_tab *burned_subs)
{
	static char buffer[1000];
#ifdef _WIN32
	strcpy(buffer, "ccextractorwin --gui_mode_reports");
#else
	strcpy(buffer, "./ccextractor --gui_mode_reports");
#endif

	/*INPUT COMMANDS*/
	if (main_settings->port_or_files == FILES)
	{
		if (input->type_select != 0)
		{
			strcat(buffer, " -in=");
			strcat(buffer, input->type[input->type_select]);
		}

		if (input->is_split)
			strcat(buffer, " --videoedited");

		if (input->is_process_from)
		{
			strcat(buffer, " -startat ");
			strcat(buffer, input->from_time_buffer);
		}

		if (input->is_process_until)
		{
			strcat(buffer, " -endat ");
			strcat(buffer, input->until_time_buffer);
		}

		switch (input->elementary_stream)
		{
			case AUTO_DETECT:
				break;
			case STREAM_TYPE:
				strcat(buffer, " -datastreamtype ");
				strncat(buffer, input->stream_type, input->stream_type_len);
				break;
			case STREAM_PID:
				strcat(buffer, " -datapid ");
				strncat(buffer, input->stream_pid, input->stream_pid_len);
		}

		if (input->is_assume_mpeg)
		{
			strcat(buffer, " -streamtype ");
			strncat(buffer, input->mpeg_type, input->mpeg_type_len);
		}

		if (decoders->teletext_dvb == TELETEXT)
		{
			switch (input->teletext_decoder)
			{
				case AUTO_DECODE:
					break;
				case FORCE:
					strcat(buffer, " -teletext");
					break;
				case DISABLE:
					strcat(buffer, " -noteletext");
			}

			if (input->is_process_teletext_page)
			{
				strcat(buffer, " -tpage ");
				strncat(buffer, input->teletext_page_number, input->teletext_page_numer_len);
			}
		}

		switch (input->is_limit)
		{
			case NO_LIMIT:
				break;
			case LIMITED:
				strcat(buffer, " --screenfuls ");
				strcat(buffer, input->screenful_limit_buffer);
		}

		switch (input->clock_input)
		{
			case AUTO:
				break;
			case GOP:
				strcat(buffer, " --goptime");
				break;
			case PTS:
				strcat(buffer, " --nogoptime");
				break;
		}
	}

	/*Main tab and network settings*/
	if (main_settings->port_or_files == PORT)
	{
		switch (main_settings->port_select)
		{
			case 0:
				strcat(buffer, " -udp ");
				if (!strstr(network_settings->udp_ipv4, "None"))
				{
					strncat(buffer, network_settings->udp_ipv4, network_settings->udp_ipv4_len);
					strcat(buffer, ":");
				}
				strncat(buffer, main_settings->port_num, main_settings->port_num_len);
				break;
			case 1:
				strcat(buffer, " -tcp ");
				strncat(buffer, main_settings->port_num, main_settings->port_num_len);
				if (!strstr(network_settings->tcp_pass, "None"))
				{
					strcat(buffer, " -tcppassword ");
					strncat(buffer, network_settings->tcp_pass, network_settings->tcp_pass_len);
				}
				if (!strstr(network_settings->tcp_desc, "None"))
				{
					strcat(buffer, " -tcpdesc ");
					strncat(buffer, network_settings->tcp_desc, network_settings->tcp_desc_len);
				}
				break;
			default:
				break;
		}

		if (input->is_live_stream)
		{
			strcat(buffer, " -s ");
			strncat(buffer, input->wait_data_sec, input->wait_data_sec_len);
		}

		if (input->is_process_from)
		{
			strcat(buffer, " -startat ");
			strcat(buffer, input->from_time_buffer);
		}

		if (input->is_process_until)
		{
			strcat(buffer, " -endat ");
			strcat(buffer, input->until_time_buffer);
		}

		switch (input->elementary_stream)
		{
			case AUTO_DETECT:
				break;
			case STREAM_TYPE:
				strcat(buffer, " -datastreamtype ");
				strncat(buffer, input->stream_type, input->stream_type_len);
				break;
			case STREAM_PID:
				strcat(buffer, " -datapid ");
				strncat(buffer, input->stream_pid, input->stream_pid_len);
		}

		if (input->is_assume_mpeg)
		{
			strcat(buffer, " -streamtype ");
			strncat(buffer, input->mpeg_type, input->mpeg_type_len);
		}

		switch (input->teletext_decoder)
		{
			case AUTO_DECODE:
				break;
			case FORCE:
				strcat(buffer, " -teletext");
				break;
			case DISABLE:
				strcat(buffer, " -noteletext");
		}

		if (input->is_process_teletext_page)
		{
			strcat(buffer, " -tpage ");
			strncat(buffer, input->teletext_page_number, input->teletext_page_numer_len);
		}

		switch (input->is_limit)
		{
			case NO_LIMIT:
				break;
			case LIMITED:
				strcat(buffer, " --screenfuls ");
				strcat(buffer, input->screenful_limit_buffer);
		}

		switch (input->clock_input)
		{
			case AUTO:
				break;
			case GOP:
				strcat(buffer, " --goptime");
				break;
			case PTS:
				strcat(buffer, " --nogoptime");
				break;
		}
	}

	/*ADVANCED INPUT SETTINGS*/
	if (advanced_input->is_multiple_program)
	{
		switch (advanced_input->multiple_program)
		{
			case FIRST_PROG:
				strcat(buffer, " -autoprogram");
				break;
			case PROG_NUM:
				strcat(buffer, " -pn ");
				strcat(buffer, advanced_input->prog_number);
				break;
		}
	}

	switch (advanced_input->set_myth)
	{
		case AUTO_MYTH:
			break;
		case FORCE_MYTH:
			strcat(buffer, " -myth");
			break;
		case DISABLE_MYTH:
			strcat(buffer, " -nomyth");
			break;
	}

	if (advanced_input->is_mpeg_90090)
		strcat(buffer, " -90090");
	if (advanced_input->is_padding_0000)
		strcat(buffer, " -fp");
	if (advanced_input->is_order_ccinfo)
		strcat(buffer, " -poc");
	if (advanced_input->is_win_bug)
		strcat(buffer, " -wtvconvertfix");
	if (advanced_input->is_hauppage_file)
		strcat(buffer, " -haup");
	if (advanced_input->is_process_mp4)
		strcat(buffer, " -mp4vidtrack");
	if (advanced_input->is_ignore_broadcast)
		strcat(buffer, " -noautotimeref");

	/*DECODERS TAB*/
	if (decoders->is_field2)
		strcat(buffer, " -12");

	switch (decoders->channel)
	{
		case CHANNEL_1:
			break;
		case CHANNEL_2:
			strcat(buffer, " -cc2");
			break;
	}

	if (decoders->is_708)
	{
		strcat(buffer, " -svc ");
		strncat(buffer, decoders->services, decoders->services_len);
	}

	switch (decoders->teletext_dvb)
	{
		case TELETEXT:
			if (strcmp(decoders->min_distance, "2"))
			{
				strcat(buffer, " -levdistmincnt ");
				strncat(buffer, decoders->min_distance, decoders->min_distance_len);
			}
			if (strcmp(decoders->max_distance, "10"))
			{
				strcat(buffer, " -levdistmaxpct ");
				strncat(buffer, decoders->max_distance, decoders->max_distance_len);
			}
			break;

		case DVB:
			strcat(buffer, " -codec dvdsub");
			break;
	}

	/*CREDITS TAB*/
	if (credits->is_start_text)
	{
		strcat(buffer, " --startcreditstext \"");
		strncat(buffer, credits->start_text, credits->start_text_len);
		strcat(buffer, "\" --startcreditsforatleast ");
		strncat(buffer, credits->start_atleast_sec, credits->start_atleast_sec_len);
		strcat(buffer, " --startcreditsforatmost ");
		strncat(buffer, credits->start_atmost_sec, credits->start_atmost_sec_len);
		if (credits->is_before)
		{
			strcat(buffer, " --startcreditsnotbefore ");
			strcat(buffer, credits->before_time_buffer);
		}
		if (credits->is_after)
		{
			strcat(buffer, " --startcreditsnotafter ");
			strcat(buffer, credits->after_time_buffer);
		}
	}

	if (credits->is_end_text)
	{
		strcat(buffer, " --endcreditstext \"");
		strncat(buffer, credits->end_text, credits->end_text_len);
		strcat(buffer, "\" --endcreditsforatleast ");
		strncat(buffer, credits->end_atleast_sec, credits->end_atleast_sec_len);
		strcat(buffer, " --endcreditsforatmost ");
		strncat(buffer, credits->end_atmost_sec, credits->end_atmost_sec_len);
	}

	/*DEBUG TAB*/
	if (debug->is_elementary_stream)
	{
		strcat(buffer, " -cf ");
		strncat(buffer, debug->elementary_stream, debug->elementary_stream_len);
	}
	if (debug->is_dump_packets)
		strcat(buffer, " -debug");
	if (debug->is_debug_608)
		strcat(buffer, " -608");
	if (debug->is_debug_708)
		strcat(buffer, " -708");
	if (debug->is_stamp_output)
		strcat(buffer, " -goppts");
	if (debug->is_debug_analysed_vid)
		strcat(buffer, " -vides");
	if (debug->is_raw_608_708)
		strcat(buffer, " -cbraw");
	if (debug->is_debug_parsed)
		strcat(buffer, " -parsedebug");
	if (!strcmp(output->type[output->type_select], "bin"))
	{
		if (debug->is_disable_sync)
			strcat(buffer, " -nosync");
		if (debug->is_no_padding)
			strcat(buffer, " -fullbin");
	}
	if (debug->is_debug_xds)
		strcat(buffer, " -xdsdebug");
	if (debug->is_output_pat)
		strcat(buffer, " -parsePAT");
	if (debug->is_output_pmt)
		strcat(buffer, " -parsePMT");
	if (debug->is_scan_ccdata)
		strcat(buffer, " -investigate_packets");
	if (debug->is_output_levenshtein)
		strcat(buffer, " -deblev");

	/*HARD_BURNED SUBS SETTINGS*/
	if (burned_subs->is_burned_subs)
	{
		strcat(buffer, " -hardsubx -ocr_mode");
		switch (burned_subs->ocr_mode)
		{
			case FRAME_WISE:
				strcat(buffer, " frame");
				break;
			case WORD_WISE:
				strcat(buffer, " word");
				break;
			case LETTER_WISE:
				strcat(buffer, " letter");
				break;
		}

		strcat(buffer, " -min_sub_duration ");
		strcat(buffer, burned_subs->min_duration);

		if (!burned_subs->subs_color_select && burned_subs->color_type == PRESET)
			sprintf(buffer, "%s -whiteness_thresh %d", buffer, burned_subs->luminance_threshold);

		sprintf(buffer, "%s -conf_thresh %d", buffer, burned_subs->confidence_threshold);

		if (burned_subs->is_italic)
			strcat(buffer, " -detect_italics");
	}

	//Output
	{
		strcat(buffer, " -out=");
		strcat(buffer, output->type[output->type_select]);
		if (output->is_filename)
		{
			strcat(buffer, " -o \"");
			strncat(buffer, output->filename, output->filename_len);
			strcat(buffer, "\"");
		}

		if (output->is_delay)
		{
			strcat(buffer, " -delay ");
			strcat(buffer, output->delay_sec_buffer);
		}

		if (output->is_export_xds)
			strcat(buffer, " -xds");

		switch (output->encoding)
		{
			case LATIN:
				strcat(buffer, " -latin1");
				break;
			case UNIC:
				strcat(buffer, " -unicode");
				break;
			case UTF:
				strcat(buffer, " -utf8");
				break;
		}

		if (output->is_bom)
			strcat(buffer, " -bom");
		else
			strcat(buffer, " -nobom");

		if (output->is_cap_standard)
			strcat(buffer, " --sentencecap");

		if (output->is_cap_file)
		{
			strcat(buffer, " --capfile \"");
			strncat(buffer, output->cap_dictionary, output->cap_dictionary_len);
			strcat(buffer, "\"");
		}

		switch (output->line_ending)
		{
			case CRLF:
				break;
			case LF:
				strcat(buffer, " -lf");
				break;
		}

		if (output->is_center)
			strcat(buffer, " -trim");

		if (output->is_dash)
			strcat(buffer, " -autodash");

		if (output->no_typesetting)
			strcat(buffer, " --notypesetting");

		switch (output->font_color)
		{
			case NO_COLOR:
				strcat(buffer, " --nofontcolor");
				break;
			case DEFAULT_COLOR:
				strcat(buffer, " --defaultcolor #");
				strcat(buffer, output->color_hex);
				break;
		}

		switch (output->onetime_or_realtime)
		{
			case ONETIME:
				strcat(buffer, " --norollup");
				break;
			case REALTIME:
				strcat(buffer, " -dru");
				switch (output->roll_limit_select)
				{
					case 1:
						strcat(buffer, " -ru1");
						break;
					case 2:
						strcat(buffer, " -ru2");
						break;
					case 3:
						strcat(buffer, " -ru3");
						break;
					default:
						break;
				}
		}
	}

	memset(command->term_string, 0, sizeof(command->term_string));
	strncpy(command->term_string, buffer, strlen(buffer));
}
