#!/usr/bin/perl -w

package SPARCplug;

use Tk;
use Tk::Table;
use Tk::LabFrame;
use Tk::Dialog;
use Tk::BrowseEntry;
use IO::File;

#main_window_create();
#MainLoop;
#exit (0);
return 1;

our $selected_band='x';

sub main_window_create {
	our @recipe_names;
	
	$mw = MainWindow->new;
	$mw->title("SPARKplug");
	$mw->configure( -width => "1600" );
	main_window_create_menubar();

	my $top_frame =
	  $mw->Frame( -relief => 'ridge', -borderwidth => 2 )
	  ->pack( -side => 'top', -anchor => 'nw', -expand => 0, -fill => 'none' );
	  
	my $req_cal_frame =
		$top_frame->LabFrame( -label => "Required calibration files")
		->pack( -side => 'right', -anchor => 'ne', -expand => 0, -fill => 'none' );
	$req_cal_box =
	  $req_cal_frame->Scrolled( 'Text', -scrollbars => 'osoe', -height => 10 )
	  ->pack( -side => 'left', -expand => 1, -fill => 'both' );

	my $sel_frame =
	  $top_frame->LabFrame( -label => "Selection" )
	  ->pack( -side => 'left', -anchor => 'w', -expand => 0, -fill => 'none' );

	my $recipe_frame = $sel_frame->Frame()->pack( -side => 'left' );
	my $recipe_label =
	  $recipe_frame->Label( -text => "Recipe: " )->pack( -side => 'left' );
	$gui_recipe_box = $recipe_frame->Scrolled(
		"Listbox",
		-scrollbars      => "osoe",
		-selectmode      => "single",
		-height          => 5,
		-exportselection => 0
	)->pack( -side => 'left' );
	$gui_recipe_box->bind( '<Button-1>', \&main_window_gui_recipe_box_cb );

	$gui_recipe_box->insert( 'end', @recipe_names );

	my $template_frame = $sel_frame->Frame()->pack( -side => 'left' );
	my $template_label =
	  $template_frame->Label( -text => "Template: " )->pack( -side => 'left' );
	$gui_template_box = $template_frame->Scrolled(
		"Listbox",
		-scrollbars      => "osoe",
		-selectmode      => "single",
		-height          => 5,
		-width           => 32,
		-exportselection => 0
	)->pack( -side => 'left' );
	$gui_template_box->bind(
		'<Button-1>',
		sub {
			main_window_populate_raw_files_box();
			main_window_update_sof();
		}
	);

	my $band_frame = $sel_frame->Frame()->pack( -side => 'left' );
	my $band_label =
	  $band_frame->Label( -text => "Band: " )->pack( -side => 'left' );
	$gui_band_box = $band_frame->Scrolled(
		"Listbox",
		-scrollbars      => "oe",
		-selectmode      => "single",
		-height          => $#band_names + 1,
		-width           => 5,
		-exportselection => 0
	)->pack( -side => 'left' );
	$gui_band_box->bind(
		'<Button-1>',
		sub {
			@raw_file_selection=();
			$gui_selected_raw_files->delete( 0, "end" );
			$selected_band='x';
			main_window_automatic_cal_selection();
			main_window_populate_raw_files_box();
			main_window_populate_cal_files_box();
			main_window_update_sof();
		}
	);
	$gui_band_box->insert( 'end', @band_names );
	$gui_band_box->selectionSet('end');

	my $rotangle_frame = $sel_frame->Frame()->pack( -side => 'left' );
	$rotangle_label =
	  $rotangle_frame->Label( -text => "Rotation\nAngle: " )
	  ->pack( -side => 'left' );
	$gui_rotangle_box = $rotangle_frame->Scrolled(
		"Listbox",
		-scrollbars      => "oe",
		-selectmode      => "single",
		-height          => $#rot_angles + 1,
		-width           => 6,
		-exportselection => 0
	)->pack( -side => 'left' );
	$gui_rotangle_box->bind(
		'<Button-1>',
		sub {
			my $rotangle =
			  $gui_rotangle_box->get( $gui_rotangle_box->curselection() );
			$gui_rotangle_box->selectionSet("end") if $rotangle eq "ignore";
			$rotation_angle = $rotangle;
			$rotangle_label->configure(
				-text => "Rotation\nAngle:\n\n$rotation_angle" );
			main_window_populate_raw_files_box();
			main_window_update_sof();
		}
	);
	$gui_rotangle_box->insert( 'end', @rot_angles );
	$gui_rotangle_box->selectionSet('end');
	$rotation_angle = $gui_rotangle_box->get( $gui_rotangle_box->curselection() );
	$rotangle_label->configure(
				-text => "Rotation\nAngle:\n\n$rotation_angle" );

	my $file_frame =
	  $mw->LabFrame( -label => "Files" )
	  ->pack( -side => 'top', -anchor => 'n', -expand => 1, -fill => 'both' );

	my $notebook =
	  $file_frame->NoteBook()
	  ->pack( -side => 'top', -anchor => 'n', -expand => 1, -fill => 'both' );
	$nb_raw = $notebook->add( 'raw', -label => "Raw Files" );
	$nb_cal = $notebook->add( 'cal', -label => "Calibration Files" );
	$nb_selected_raw = $notebook->add( 'sel', -label => "Selected Raw Files" );

	$gui_raw_files = $nb_raw->Scrolled(
		'MListbox',
		-scrollbars => 'osoe',
		-selectmode => "multiple",
		-width      => "1200",
		-columns    => main_window_set_raw_columns(),
	)->pack( -expand => 1, -fill => 'both' );
	$gui_raw_files->columnHide(0);
	$gui_raw_files->bindRows(
		'<Button-1>',
		sub {
			my @cur_selection = $gui_raw_files->curselection();
			my (%m, $item, $selectedIndex);
			foreach $item (@cur_selection,@raw_file_selection,) { $m{$item}++;}
			foreach $item (keys %m) {
				if ($m{$item} == 1) {
					$selectedIndex = $item;
					last;
				}
			}
			if ($#raw_file_selection > $#cur_selection) {
				#entry is removed from selection
				my $entry_str = join(",",$gui_raw_files->getRow($selectedIndex));
				for ( my $sx = 0 ; $sx < $gui_selected_raw_files->index('end') ; $sx++ ) {
					if ($entry_str eq join( ",", $gui_selected_raw_files->getRow($sx))) {
						$gui_selected_raw_files->delete($sx,$sx);
						last;
					}
				}
			} else {
				#new entry selected
				$gui_selected_raw_files->insert( "end",
					$gui_raw_files->get($selectedIndex,$selectedIndex));
				my $file = $gui_raw_files->getRow($selectedIndex);
				my $band = $raw_headers{"$file"}{filter_band};
				if ($selected_band eq 'x' && $band ne "Block") {
					$selected_band = $band;
					main_window_automatic_cal_selection();
					for ( my $sx = 0 ; $sx < $gui_band_box->index('end') ; $sx++ ) {
						if ($gui_band_box->get($sx) eq $selected_band) {
							$gui_band_box->selectionSet($sx);
							last;
						}
					}
				}
			}
			@raw_file_selection = @cur_selection;
			main_window_update_sof();
		}
	);

	$gui_cal_files = $nb_cal->Scrolled(
		'MListbox',
		-scrollbars => 'osoe',
		-selectmode => "multiple",
		-width      => "1000",
		-columns    => main_window_set_cal_columns(),
	)->pack( -expand => 1, -fill => 'both' );
	$gui_cal_files->columnHide(0);
	$gui_cal_files->bindRows(
		'<Button-1>',
		sub {
			my @sels = $gui_cal_files->curselection();
			@rows = $gui_cal_files->get( 0, "end" );
			foreach my $row (@rows) { $row->[1] = ' '; }
			foreach my $sel (@sels) { $rows[$sel][1] = 'x'; }
			$gui_cal_files->delete( 0, "end" );
			$gui_cal_files->insert( "end", @rows );
			foreach my $sel (@sels) {
				$gui_cal_files->selectionSet( $sel, $sel );
			}
			main_window_update_sof();
		}
	);
	
	$gui_selected_raw_files = $nb_selected_raw->Scrolled(
		'MListbox',
		-scrollbars => 'osoe',
		-selectmode => "single",
		-width      => "1200",
		-columns    => main_window_set_raw_columns(),
	)->pack( -expand => 1, -fill => 'both' );
	$gui_selected_raw_files->columnHide(0);
	$gui_selected_raw_files->bindRows(
		'<Button-1>',
		sub {
			my @sels = $gui_selected_raw_files->curselection();
			my @srow = $gui_selected_raw_files->getRow($sels[0]);
			my $test = join(",", @srow);
			$gui_selected_raw_files->delete($sels[0],$sels[0]);
			for (my $ix=0; $ix<$gui_raw_files->index('end'); $ix++) {
				my @row = $gui_raw_files->getRow($ix);
				if ($test eq join(",", @row)) {
					$gui_raw_files->selectionClear($ix);
					last;
				}
			}
			main_window_update_sof();
		}
	);

	my $sof_frame =
	  $mw->LabFrame( -label => "SOF" )
	  ->pack( -side => 'top', -anchor => 'n', -expand => 1, -fill => 'both' );
	$gui_sof_text =
	  $sof_frame->Scrolled( 'Text', -scrollbars => 'osoe', -height => 10 )
	  ->pack( -side => 'left', -expand => 1, -fill => 'both' );

	my $button_box =
	  $sof_frame->LabFrame( -label => "Action" )
	  ->pack( -side => 'left', -anchor => 'n', -expand => 0, -fill => 'none' );
	my $export_button = $button_box->Button(
		-text    => "Export SOF",
		-command => \&main_window_export_button_cb
	)->pack();
	my $pipeline_button = $button_box->Button(
		-text    => "Execute recipe",
		-command => \&main_window_execute_button_cb
	)->pack();
	my $pipelinehelp_button = $button_box->Button(
		-text    => "Recipe help page",
		-command => \&main_window_recipehelp_button_cb
	)->pack();

	$gui_recipe_box->selectionSet(0);
	main_window_gui_recipe_box_cb();
	$gui_template_box->selectionClear( 0, "end" );
	$gui_template_box->selectionSet("end");
	main_window_populate_raw_files_box();
}

sub main_window_gui_recipe_box_cb {
	our %template_options;
	my $recipe = $gui_recipe_box->get( $gui_recipe_box->curselection() );

	#	print "Recipe: $recipe\n";
	$gui_template_box->delete( 0, 'end' );
	$gui_template_box->insert( 'end', @{ $template_options{"$recipe"} } );
	$gui_template_box->selectionSet(0);
	$gui_band_box->selectionClear( 0, 'end' );
	$gui_band_box->selectionSet('end')
	  if !defined( $gui_band_box->curselection() );
	$selected_band='x';
	main_window_automatic_cal_selection();
	@raw_file_selection=();
	$gui_selected_raw_files->delete( 0, "end" );
	main_window_populate_raw_files_box();
	main_window_populate_cal_files_box();
	main_window_update_sof();
	
	my @requested_cal_file = @{$cal_types{$recipe}};
	$req_cal_box->delete( '1.0', 'end' );
	foreach my $entry (@requested_cal_file) {
		$req_cal_box->insert( 'end', "$entry\n" );
	}
}

sub main_window_create_menubar {

	# Create a frame for our menubar across the top of the window
	$f =
	  $mw->Frame( -relief => 'ridge', -borderwidth => 2 )
	  ->pack( -side => 'top', -anchor => 'n', -expand => 0, -fill => 'x' );

	# Create the menubutton, with two items: New Doc and a separator
	my $filem = $f->Menubutton(
		-text      => "File",
		-tearoff   => 0,
		-menuitems => [
			[
				"command" => "Reload RAW directory",
				-command  => \&main_window_reload_raw_directory,
			],
			[
				"command" => "Quit",
				-command  => \&main_window_exit,
			],
			"-"
		]
	)->pack( -side => 'left' );
	my $editm = $f->Menubutton(
		-text      => "Edit",
		-tearoff   => 0,
		-menuitems => [
			[
				"command" => "Show esorex history",
				-command  => \&main_window_show_esorex_history,
			],
			"-"
		]
	)->pack( -side => 'left' );
	my $helpm = $f->Menubutton(
		-text      => "Help",
		-tearoff   => 0,
		-menuitems => [
			[
				"command" => "About",
				-command  => \&main_window_print_help,
			],
			"-"
		]
	)->pack( -side => 'right' );
}

sub main_window_get_max {
	my $keyword = shift(@_);
	my $file;
	my $len;
	my $max_len = 0;

	foreach my $file ( keys(%raw_headers) ) {
		$len = length( $raw_headers{"$file"}[0]{"$keyword"} );
		if ( !defined $len ) {
			print "Undefined keyword $keyword in file $file\n";
			$len = 0;
		}
		$max_len = $len if ( $len > $max_len );
	}
	return $max_len;
}

sub main_window_set_raw_columns {

	our %rawfitsheader;
	our @main_raw_window_columns;
	my @cols = [];

	push @{ $cols[0] },
	  [
		-text      => "Name",
		-textwidth => 1
	  ];
	foreach my $colname (@main_raw_window_columns) {
		my $width = length( $rawfitsheader{$colname}{head} );
		my $w2    = $rawfitsheader{$colname}{maxLength};
		$width = $w2 if $w2 > $width;
		push @{ $cols[0] },
		  [
			-text      => $rawfitsheader{$colname}{head},
			-textwidth => $width
		  ];
	}

	return @cols;

}

sub main_window_check_lamp {
	my ( $file, $lampID, $lampKey, $lampValue );
	$file    = shift(@_);
	$lampID  = shift(@_);
	$lampKey = sprintf "HIERARCH ESO INS LAMP%d ST", $lampID;
	if ( defined( $raw_headers{"$file"}[0]{"$lampKey"} )
		&& $raw_headers{"$file"}[0]{"$lampKey"} eq "T" )
	{
		return 1;
	}
	else {
		return 0;
	}
}

sub main_window_lamp_string {
	my ( $file, $lamp, $lamp_key );
	$file     = shift(@_);
	$lamp     = "";
	$lamp_key = $raw_headers{"$file"}[0]{"HIERARCH ESO INS LAMP1 ST"};
	if ( defined($lamp_key) && $lamp_key eq "T" ) { $lamp = $lamp . "Ar,"; }
	$lamp_key = $raw_headers{"$file"}[0]{"HIERARCH ESO INS LAMP2 ST"};
	if ( defined($lamp_key) && $lamp_key eq "T" ) { $lamp = $lamp . "Ne,"; }
	$lamp_key = $raw_headers{"$file"}[0]{"HIERARCH ESO INS LAMP3 ST"};

	if ( defined($lamp_key) && $lamp_key eq "T" ) {
		$lamp = $lamp . "FF1,";
	}
	$lamp_key = $raw_headers{"$file"}[0]{"HIERARCH ESO INS LAMP4 ST"};
	if ( defined($lamp_key) && $lamp_key eq "T" ) {
		$lamp = $lamp . "FF2,";
	}

	if ( length($lamp) eq 0 ) {
		$lamp = "none";
	}
	else {
		$lamp = substr $lamp, 0, -1;    #skip last comma
	}
	return $lamp;
}

sub main_window_populate_raw_files_box {
	my ( @bandsel, $band_pattern, $band, $test, $rotangle, $sel);
	if ( $#_ eq 0 ) {
		$sel = shift(@_);
	}
	else {
		$sel = $gui_template_box->get( $gui_template_box->curselection() );
	}

	$gui_raw_files->delete( 0, 'end' );
	my @sel_keys;
	my ( $file, $lamp, $lamp_key );

	$band = $band_names[$#band_names];
	$band = $gui_band_box->get( $gui_band_box->curselection() )
	  if defined( $gui_band_box->curselection() );
	$band = ".*" if $band eq "ignore";
	$band_pattern = "^($band|Block)\$";

	my $rotangle_delta = 30;
	foreach my $file ( keys(%raw_headers) ) {

		$band = $raw_headers{"$file"}{filter_band};
		next if ( $band !~ /$band_pattern/ );

		$rotangle = $raw_headers{"$file"}{rot_angle};
		if ($rotangle !~ /^$/) {
			$rotangle -= 360 if ( 360 - $rotangle ) <= $rotangle_delta;
		}
		next
		  if (! ($rotation_angle eq "ignore"
		  	  || $rotangle eq ""
			  || abs( $rotation_angle - $rotangle ) <= $rotangle_delta ));

		$_    = $sel;
	  SEL_SWITCH: {
			/^ALL$/ && do {
				push( @sel_keys, $file );
				last SEL_SWITCH;
			};
			/^TPL_ID_(.*)$/ && do {
				push( @sel_keys, $file ) 
						if ( $raw_headers{"$file"}{tpl_id} =~ /^$1$/ );
				last SEL_SWITCH;
			};
			/^DPR_TYPE_(.*)$/ && do {
				push( @sel_keys, $file ) 
						if ( $raw_headers{"$file"}{dpr_type} =~ /$1/i );
				last SEL_SWITCH;
			};
			/^ALL_dark$/ && do {
				push( @sel_keys, $file ) 
						if ( $raw_headers{"$file"}{filter_band} eq "Block" );
				last SEL_SWITCH;
			};
			/^ALL_flat$/ && do {
				push( @sel_keys, $file ) 
						if ( $raw_headers{"$file"}{lamps} =~ /FF/ );
				last SEL_SWITCH;
			};
			/^ALL_wave_cal$/ && do {
				push( @sel_keys, $file ) 
						if ( $raw_headers{"$file"}{lamps} =~ /(Ar|Ne)/ );
				last SEL_SWITCH;
			};
		}
	}

	foreach my $file (@sel_keys) {
		my @cols = [];
		push @{ $cols[0] }, "$file";
		foreach my $colname (@main_raw_window_columns) {
			push @{ $cols[0] }, $raw_headers{"$file"}{$colname};
		}

		$gui_raw_files->insert( "end", @cols );
	}
	for ( my $sx = 0 ; $sx < $gui_selected_raw_files->index('end') ; $sx++ ) {
		my $test = join( ", ",  $gui_selected_raw_files->getRow($sx));
		for ( my $rx = 0 ; $rx < $gui_raw_files->index('end') ; $rx++ ) {
			if ( $test eq join( ", ",  $gui_raw_files->getRow($rx)) ) {
				$gui_raw_files->selectionSet($rx);
				last;
			}
		}
	}
	@raw_file_selection = $gui_raw_files->curselection();
}

sub main_window_set_cal_columns {
	our %calfitsheader;
	our @main_cal_window_columns;
	my @cols = [];

	# read calibrations files just to get column sizes
	our $working_directory;
	my $filepattern = "*.fits";
	my %cal_headers =
	  scan_fits_files( $working_directory . $filepattern, \%calfitsheader, 0 );
	our $cal_directory;
	%cal_headers = scan_fits_files( $cal_directory . $filepattern,
		\%calfitsheader, 0 );

	push @{ $cols[0] },
	  [
		-text      => "Name",
		-textwidth => 1
	  ];
	push @{ $cols[0] },
	  [
		-text      => "x",
		-textwidth => 1
	  ];

	foreach my $colname (@main_cal_window_columns) {
		my $width = length( $calfitsheader{$colname}{head} );
		my $w2    = $calfitsheader{$colname}{maxLength};
		$width = $w2 if $w2 > $width;
		push @{ $cols[0] },
		  [
			-text      => $calfitsheader{$colname}{head},
			-textwidth => $width
		  ];
	}

	return @cols;
}

sub main_window_populate_cal_files_box {
	my ( $band, $recipe, $dir, $type, $filename, @calfiles, $file, %header );
	my ($rotAngle);

	$band = $band_names[$#band_names];
	$band = $gui_band_box->get( $gui_band_box->curselection() )
	  if defined( $gui_band_box->curselection() );
	$band = ".*" if $band eq "ignore";
	$band_pattern = "^$band\$";

	$recipe = $gui_recipe_box->get( $gui_recipe_box->curselection() );
	$gui_cal_files->delete( 0, 'end' );

	our @main_cal_window_columns;
	our @cal_types;
	our %band_specific_cal_files;
	
	my $filepattern = "*.fits";
	our $working_directory;
	our $cal_directory;
	my $rotangle_delta = 30;

	foreach my $type ( "current", "static" ) {
		$dir = $working_directory        if $type eq "current";
		$dir = $cal_directory if $type eq "static";

		my %cal_headers =
		  scan_fits_files( $dir . $filepattern, \%calfitsheader, 0 );
		foreach my $file ( keys(%cal_headers) ) {
			$cal_headers{"$file"}{type} = $type;
			$band                       = $cal_headers{"$file"}{band1};
			$cal_headers{"$file"}{band} = $band if $band;
			$band                       = $cal_headers{"$file"}{band2};
			$cal_headers{"$file"}{band} = $band if $band;
			$band                       = $cal_headers{"$file"}{band};
			my $category = $cal_headers{"$file"}{category};
			my $rotangle;
			if (defined($cal_headers{"$file"}{rot_angle}) &&
				$cal_headers{"$file"}{rot_angle} ne "") {
				$rotangle = $cal_headers{"$file"}{rot_angle};
			} else {
				$rotangle = $rotation_angle; # fits always
			}
			$rotangle -= 360 if ($rotation_angle ne "ignore") && 
								(( 360 - $rotangle ) <= $rotangle_delta);

			next if !scalar grep /$category/, @{ $cal_types{$recipe} };
			next
			  if $band_specific_cal_files{$category}
				  && ( $band !~ /$band_pattern/ );
			next
			  if $rotation_angle ne "ignore"
				  && ( abs( $rotation_angle - $rotangle ) >= $rotangle_delta );

			my @cols = [];
			push @{ $cols[0] }, "$file";
			push @{ $cols[0] }, " ";
			foreach my $colname (@main_cal_window_columns) {
				push @{ $cols[0] }, $cal_headers{"$file"}{$colname};
			}

			$gui_cal_files->insert( "end", @cols );

			$cal_headers{"$file"}{type} = $type;
		}
	}
	return;
}

sub main_window_set_staticcal_columns {

	return [
		[ -text => "File",     -textwidth => 40 ],
		[ -text => "DATE",     -textwidth => 24 ],
		[ -text => "PRO CATG", -textwidth => 24 ],
	];
}

sub main_window_automatic_cal_selection {
	
}

sub main_window_update_sof {
	my ( @sels, $recipe, $sel, $file, $dir, $tag, %entries, $maxlen, $ix);

	$recipe = $gui_recipe_box->get( $gui_recipe_box->curselection() );
	$gui_sof_text->delete( '1.0', 'end' );

	for ($ix = 0; $ix < $gui_selected_raw_files->index('end'); $ix++) {
		$file = $gui_selected_raw_files->getRow($ix);
		
	  TAG_SWITCH: {
			$recipe eq "kmo_dark" && do {
				$tag = "DARK";
				last TAG_SWITCH;
			};
			$recipe eq "kmo_flat" && do {
				if (   $raw_headers{"$file"}{filter_band} eq "Block"
					|| $raw_headers{"$file"}{lamps} eq "none" )
				{
					$tag = "FLAT_OFF";
				}
				else {
					$tag = "FLAT_ON";
				}
				last TAG_SWITCH;
			};
			$recipe eq "kmo_wave_cal" && do {
				if (   $raw_headers{"$file"}{filter_band} eq "Block"
					|| $raw_headers{"$file"}{lamps} eq "none" )
				{
					$tag = "ARC_OFF";
				}
				else {
					$tag = "ARC_ON";
				}
				last TAG_SWITCH;
			};
			$recipe eq "kmo_illumination" && do {
				$tag = "FLAT_SKY";
				last TAG_SWITCH;
			};
			$recipe eq "kmo_std_star" && do {
				$tag = "STD";
				last TAG_SWITCH;
			};
			$recipe eq "kmo_sci_red" && do {
				$tag = "SCIENCE";
				last TAG_SWITCH;
			};
			$recipe eq "kmo_reconstruct" && do {
				if ($raw_headers{"$file"}{filter_band} eq "Block") {
					$tag = "DARK";
				} else {
					$tag = "OBJECT";
				}
				last TAG_SWITCH;
			};
		}
		$entries{"$file"} = $tag;
	}

	@sels = $gui_cal_files->curselection();
	foreach my $sel (@sels) {
		$file = $gui_cal_files->getRow($sel);
		$tag  = uc $1 if ( $file =~ /(\w*?)\.fits$/ );
		$tag  = uc $1
		  if ( $file =~
			/(\w*?)_([A-Z]{6}|[A-Z]{3})\.fits$/ );
#		$dir              = $working_directory;
#		$dir              = $cal_directory if $type eq "static";
		$entries{"$file"} = $tag;
	}

	$maxlen = 0;
	foreach my $sel ( keys(%entries) ) {
		my $len = length($sel);
		$maxlen = $len if ( $len > $maxlen );
	}
	foreach my $sel ( sort keys(%entries) ) {
		my $entry = sprintf "%-*s    %s\n", $maxlen, $sel, $entries{"$sel"};
		$gui_sof_text->insert( 'end', $entry );
	}
}

sub main_window_exit {
	$mw->destroy();
}

sub main_window_print_help {
	print "SPARKplug V0.1\n";
}

sub main_window_show_esorex_history {
	my $tll = $mw->Toplevel( -title => "pipeline execution history" );
	my $textbox = $tll->Scrolled(
		'Text',
		-scrollbars => 'osoe',
		-width      => 160,
		-wrap       => 'none'
	  )->pack(
		-side   => 'top',
		-anchor => 'n',
		-expand => 1,
		-fill   => 'both'
	  );
	my $button =
	  $tll->Button( -text => "Close", -command => sub { $tll->destroy } )
	  ->pack();

	foreach my $cmd (@esorex_cmds) {
		$textbox->insert( 'end', "======== $cmd->{time} ========\n");
		$textbox->insert( 'end', "cat > $cmd->{sofname} <<EOF\n");
		$textbox->insert( 'end', $cmd->{sofcontent});
		$textbox->insert( 'end', "EOF\n");
		$textbox->insert( 'end', "$cmd->{cmd}\n" );
	}
	$tll->update;
}

sub main_window_export_button_cb {
	local *SOF;
	my $file = $mw->getSaveFile(
		-filetypes => [ [ 'SOF files', '.sof' ], [ 'All files', '.*' ] ],
		-initialdir => ".",
		-title      => "Export SOF",
	);
	if ( defined($file) ) {
		if ( !open( SOF, ">$file" ) ) {
			printError("Can't open SOF $file");
			return;
		}
		print SOF $gui_sof_text->get( '1.0', 'end' );
		close SOF;
	}
}

sub main_window_execute_button_cb {
	my ( $recipe, %recipe_options, @recipe_options_frames, $msg_level );

	$recipe = $gui_recipe_box->get( $gui_recipe_box->curselection() );

	my $tl = $mw->Toplevel( -title => "pipeline options" );
	my $rof = $tl->LabFrame( -label => "Basic recipe options" )->pack;
	%recipe_options = %{ $pipeline_basic_options{$recipe} };
	foreach my $key ( sort ( keys %recipe_options ) ) {
		my $f = $rof->Frame()->pack;
		push @recipe_options_frames, $f;
		my $label = $f->Label( -text => "$key" )->pack( -side => 'left' );
		my $entry = $f->Entry()->pack( -side => 'left' );
		$entry->insert( 0, $recipe_options{"$key"} );
	}
	my $arof = $tl->LabFrame( -label => "Advanced recipe options" )->pack;
	%recipe_options = %{ $pipeline_advanced_options{$recipe} };
	foreach my $key ( sort ( keys %recipe_options ) ) {
		my $f = $arof->Frame()->pack;
		push @recipe_options_frames, $f;
		my $label = $f->Label( -text => "$key" )->pack( -side => 'left' );
		my $entry = $f->Entry()->pack( -side => 'left' );
		$entry->insert( 0, $recipe_options{"$key"} );
	}
	my $emof = $tl->LabFrame( -label => "Esorex message options" )->pack;
	my $msg_level_box = $emof->BrowseEntry(
		-label    => "Message level",
		-choices  => [ 'debug', 'info', 'warning', 'error', 'off' ],
		-variable => \$esorex_msg_level
	)->pack( -side => 'top' );

	my $ok = $tl->Button(
		-text    => "OK",
		-command => [
			\&main_window_start_pipeline_cb, $tl,
			$recipe,                         @recipe_options_frames
		]
	)->pack( -side => 'bottom' );
}

sub main_window_start_pipeline_cb {
	my ( $tl, $recipe, @frames ) = @_;
	my $recipe_options = "";
	foreach my $frame (@frames) {
		my ( $labelwidget, $entrywidget ) = $frame->children;
		my $user_input = $entrywidget->get();
		if ( $user_input !~ /^\s*$/ ) {
			my $label = $labelwidget->cget( -text );
			$recipe_options .= " --$label=$user_input";
			if ( defined( $pipeline_basic_options{$recipe}{$label} ) ) {
				$pipeline_basic_options{$recipe}{$label} = $user_input;
			}
			if ( defined( $pipeline_advanced_options{$recipe}{$label} ) ) {
				$pipeline_advanced_options{$recipe}{$label} = $user_input;
			}
		}
	}

	local *SOF;
	my $soffile = $recipe;
	$soffile = $1 if ( $recipe =~ /kmo_(.*)/ );
	$soffile .= "_" . sprintf( "%x", `date +%s` ) . ".sof";
	if ( !open( $SOF, ">", $soffile) ) {
		printError("Can't open SOF $soffile");
		return;
	}
	print $SOF $gui_sof_text->get( '1.0', 'end' );
	close $SOF;

	$tl->destroy;

	my $cmd =
	  "esorex --msg-level=$esorex_msg_level $recipe $recipe_options $soffile";
	print "$cmd\n";
	
	my $sofcontent = $gui_sof_text->get( '1.0', 'end' );
	chop $sofcontent;
	push @esorex_cmds, ( { 	time => scalar localtime(),
							cmd => $cmd,
							sofname => $soffile,
							sofcontent => $sofcontent,
				});
	main_window_execucte_pipeline($cmd);
}

sub main_window_execucte_pipeline {
	my ($cmd) = @_;

	my $tll = $mw->Toplevel( -title => "pipeline execution: $cmd" );
	my $textbox = $tll->Scrolled(
		'Text',
		-scrollbars => 'osoe',
		-width      => 160,
		-wrap       => 'none'
	  )->pack(
		-side   => 'top',
		-anchor => 'n',
		-expand => 1,
		-fill   => 'both'
	  );

	local *ESOREXPIPE;
	if ( !open( ESOREXPIPE, "$cmd 2>&1 |" ) ) {
		printError("Can't open execute command $cmd");
		return;
	}

	#	my $bs = new IO::BufferedSelect(fileno(ESOREXPIPE));
	my $bs = new IO::BufferedSelect( \*ESOREXPIPE );

	my $end_exec = 0;
	while ( !$end_exec ) {
		my @ready = $bs->read_line(0.2);
		foreach (@ready) {
			my ( $fh, $line ) = @$_;
			if ( !defined $line ) {
				$end_exec = 1;
				last;
			}
			print "$line";
			$textbox->insert( 'end', $line );
			$textbox->see('end');
			$textbox->update;
		}
		my $cb_status = 1;
		until ( $cb_status == 0 ) {
			$cb_status = $mw->DoOneEvent( Tk::ALL_EVENTS | Tk::DONT_WAIT );
		}
	}
	close ESOREXPIPE;
	my $button =
	  $tll->Button( -text => "Close", -command => sub { $tll->destroy } )
	  ->pack();
}

sub main_window_recipehelp_button_cb {
	my $recipe    = $gui_recipe_box->get( $gui_recipe_box->curselection() );
	my $help_text = `esorex --man-page $recipe`;
	my $tl        = $mw->Toplevel( -title => "Recipe help page" );
	my $text =
	  $tl->Scrolled( 'Text', -scrollbars => 'osoe' )
	  ->pack( -side => 'top', -expand => 1, -fill => 'both' );
	$text->insert( 'end', $help_text );
	$text->configure( -state => "disabled" );
	my $button =
	  $tl->Button( -text => 'OK', -command => sub { $tl->destroy } )->pack;

}

#TODO main_window_reload_raw_directory
sub main_window_reload_raw_directory {
	print "To be implented\n";
}
