#!/usr/bin/perl


##this program creates a web page with an editor for a
##WeBWorK problem.  it is called by processProblem8.pl


use strict;
use lib '/ww/webwork/development/'; # mainWeBWorKDirectory;
use CGI qw(:standard escapeHTML unescapeHTML);
use MIME::Base64 qw( encode_base64 decode_base64) ;
use Global;
use Auth;
use Safe;
$main::safeCompartment = 0;
$main::safeCompartment = new Safe;

#Set to 1 to log timing data. Set to 0 to disable log.
$main::logTimingData = 0;

# begin Timing code
if( $main::logTimingData == 1 ) {
	use Benchmark;
	$main::beginTime = new Benchmark;
}
# end Timing code

my $cgi = new CGI;
my %inputs = $cgi -> Vars();

# get information from CGI inputs  (see also below for additional information)
my $Course			=	$inputs{'course'};
my $User			=	$inputs{'user'};
my $Session_key		=	$inputs{'key'};
my $randpsvn		=	22222; #int rand(1111,9999);
my $psvn			=	$inputs{'probSetKey'};  #psvn stands for Problem Set Version Number
my $probNum			=	1;
	$probNum		=	$inputs{'probNum'}	if defined($inputs{'probNum'});
my $nextProbNum		=	$probNum + 1		if defined($probNum);
my $previousProbNum	=	$probNum - 1		if defined($probNum);
my $mode			=	"HTML";
	$mode			=	$inputs{'Mode'}		if defined( $inputs{'Mode'} );
my $showEdit		=	$inputs{'showEdit'};
my $seed			=	$inputs{'seed'}		if defined( $inputs{'seed'} );
my $Rows			=	$Global::editor_window_rows;
	$Rows			=	$inputs{'Rows'}		if defined( $inputs{'Rows'} );
my $Columns			=	$Global::editor_window_columns;
$Columns			=	$inputs{'Columns'}	if defined( $inputs{'Columns'} );

# verify that information has been received
unless($Course && $User && $Session_key && $psvn) {
	&wwerror( "$0, missing data",
		"The script did not receive the proper input data.
		course is $Course, user is $User, session key is $Session_key, psvn is $psvn",'','',
	query_string() );
}


# establish environment for this script
&Global::getCourseEnvironment($Course);
my $macroDirectory			=	getCourseMacroDirectory();
my $databaseDirectory		=	getCourseDatabaseDirectory();
my $htmlDirectory			=	getCourseHtmlDirectory();
my $htmlURL					=	getCourseHtmlURL();
my $scriptDirectory			=	getWebworkScriptDirectory();
my $templateDirectory		=	getCourseTemplateDirectory();
my $courseScriptsDirectory	=	getCourseScriptsDirectory();

require "${courseScriptsDirectory}$Global::displayMacros_pl";
require "${scriptDirectory}$Global::DBglue_pl";
require "${scriptDirectory}$Global::HTMLglue_pl";
require "${scriptDirectory}$Global::FILE_pl";
#require "${scriptDirectory}qz2sub.pl";   #require this only if it actually used

my $permissionsFile	=	&Global::getCoursePermissionsFile($Course);
my $permissions		=	&get_permissions($User,$permissionsFile);

my $keyFile			=	&Global::getCourseKeyFile($Course);


# log access
&Global::log_info('', query_string);

unless ($User eq "practice666" ) {
	#verify session key
	&verify_key($User, $Session_key, "$keyFile", $Course);
}

&attachProbSetRecord($psvn);

# get problem name
my $probFileName	=	&getProblemFileName($probNum,$psvn);
$probFileName		=	$inputs{'probFileName'} if defined($inputs{'probFileName'});

# get the text source of the problem

my $source	= '';
my $comment	= '';

#print "content-type: text/html\n\ninputs of action is $inputs{action}<BR>" if defined($inputs{action});

if ( ($inputs{'action'} eq 'Revert to original and Resize window') || !(defined($inputs{'source'}) ) )  {
	$comment = '<h2> Using source from disk</h2>';

	if (-e "${templateDirectory}$probFileName" ) {
		#print "|$probFileName|<BR>";
		unless (-r "${templateDirectory}$probFileName") {
			wwerror($0, "Can't read ${templateDirectory}$probFileName");
		}

		open(PROB,"<${templateDirectory}$probFileName");
		$source = join("",<PROB>);
			close(PROB);
	}
	else {
		wwerror($0, "<H4>Error: The problem ${templateDirectory}$probFileName could not be found!</H4>");
	}
}
else {			#source is coming from HTML hidden tag; should be decoded
	$source = decodeSource( $inputs{'source'}) ;

#     if ( defined($inputs{'source_encoded_using'}) ) {  # the source has been encoded and we need to decode it first
# 		if ( $inputs{'source_encoded_using'} eq 'base64_encode' )  {
# 			$source = decode_base64($source); 
# 		} 
# 		elsif ( $inputs{'source_encoded_using'} eq 'cgi_escape' ) {
# 			$source = $cgi -> unescape($source);
# 		}
# 		elsif ( $inputs{'source_encoded_using'} eq 'none' ) {
# 			# no action required
# 		}
# 		elsif ( $inputs{'source_encoded_using'} eq 'escaped_returns' ) {
# 			$source =~ s/&#010;/\n/g;				#makes iCab work properly
# 		}
# 		else {
# 			warn "Did not recognize the source encoding method $inputs{'source_encoded_using'}";
# 		}
# 	 }
		    ##substitute carriage return with a newline
			##otherwise EndOfText construction does not work
			##browsers always have \r\n at the end of the line
		#    $source=~ s/\r\n/\n/g;

	#$source = unescapeHTML( $source );			#method in CGI.pm
}

#$source =~ s/&#010;/\n/g;				#makes iCab work properly
#my $sourceAsHTML = escapeHTML( $source );
my $display_source = $source;
$display_source = $source;    # Hard to tell what the right method for displaying text in a textarea form is.

# #check if we need to save the updated version of the text
# my $save=0;
# if ( ($inputs{'action'} eq 'Save updated version') && ($permissions == $Global::instructor_permissions)  ) {
# 	saveProblem($source, $probFileName);
# 	$save=1;
# }

#### Beginning of the Editor portion

	print 	&processProblem_htmlTOP("Editor for problem $probNum");
	print $comment;

#  	#text in case the problem has been saved
#  	if ($save) {
#  		print "<H3>Current version of the problem ${templateDirectory}$probFileName has been saved.</H3>
#  		<b>The original version has been appended to the file ${templateDirectory}$probFileName.bak . </b><BR>";
#  	}
	print "<BR>\r\n",
	    $cgi -> startform(-action=>"$Global::processProblem_CGI", -target=>"problem"),
	    "<BR>\r\n",
		$cgi -> hidden(-name=>'probNum', 	-value=>$probNum),
		$cgi -> hidden(-name=>'probSetKey', 	-value=>$psvn),

# get course, user, key
		&sessionKeyInputs(\%inputs),
		qq!
		  <STRONG>Editing file:</STRONG> $probFileName<BR>
		!,
		"Seed: ",
		$cgi -> textfield(-name=>'seed',-value=>$seed),

		" Mode: ";

# Mode button
	if ($mode eq 'HTML')  {
		print $cgi -> popup_menu(-name=>'Mode',
				-'values'=>['HTML','HTML_tth','Latex2HTML'],
				-default=>'HTML');
	} elsif ($mode eq 'HTML_tth') {
		print $cgi -> popup_menu(-name=>'Mode',
				-'values'=>['HTML','HTML_tth','Latex2HTML'],
				-default=>'HTML_tth');
	} elsif ($mode eq 'Latex2HTML') {
		print $cgi -> popup_menu(-name=>'Mode',
				-'values'=>['HTML','HTML_tth','Latex2HTML'],
				-default=>'Latex2HTML');

	} else {
		print qq! Error: unknown mode: $mode !;
	}

# Available functions list
print "<BR>Available functions: ";
print $cgi -> popup_menu( -name => 'availableFunctions',
		-values => [ qw{	DOCUMENT
							ENDDOCUMENT
							loadMacros
							beginproblem
							--------------
							TEXT
							BEGIN_TEXT
							END_TEXT
							EV3
							EV2
							--------------
							ANS
							ans_rule
							--------------
							random
							non_zero_random
							--------------
							spf
							sspf
							--------------
							begintable
							endtable
							row
							imageRow
							image
							caption
							--------------
							new_match_list
							ADDMORELATER...
							--------------
							OL
							invert
							NchooseK
							shuffle
							uniq
							lex_sort
							num_sort
						} ]
				);

print "<BR>Available Constants: ";
print $cgi -> popup_menu( -name => 'availableConstants',
		-values => [ qw{	@ALPHABET
							$PAR
							$BR
							$LQ
							$RQ
							$BM
							$EM
							$BDM
							$EDM
							$LTS
							$GTS
							$LTE
							$GTE
							$BEGIN_ONE_COLUMN
							$END_ONE_COLUMN
							$SOL
							$HINT
							$US
							$SPACE
							$BBOLD
							$EBOLD
							$HR
							$LBRACE
							$LBRACE
							$LB
							$RB
							$PI
							$E
						} ]
				);

print "<BR>Answer Evaluators: ";
print $cgi -> popup_menu( -name => 'answerEvaluators',
		-values => [ qw{	std_num_cmp
							frac_num_cmp
							arith_num_cmp
							strict_num_cmp
							--------------------
							std_num_cmp_abs
							frac_num_cmp_abs
							arith_num_cmp_abs
							strict_num_cmp_abs
							--------------------
							std_num_cmp_list
							frac_num_cmp_list
							arith_num_cmp_list
							strict_num_cmp_list
							--------------------
							std_num_cmp_abs_list
							frac_num_cmp_abs_list
							arith_num_cmp_abs_list
							strict_num_cmp_abs_list
							--------------------
							numerical_compare_with_units
							-------------------------------
							std_str_cmp
							std_cs_str_cmp
							strict_str_cmp
							unordered_str_cmp
							unordered_cs_str_cmp
							ordered_str_cmp
							ordered_cs_str_cmp
							--------------------
							std_str_cmp_list
							std_cs_str_cmp_list
							strict_str_cmp_list
							unordered_str_cmp_list
							unordered_cs_str_cmp_list
							ordered_str_cmp_list
							ordered_cs_str_cmp_list
							--------------------
							std_num_str_cmp
							-------------------------------
							function_cmp
							function_cmp_up_to_constant
							function_cmp_abs
							function_cmp_up_to_constant_abs
							multivar_function_cmp
							-------------------------------
							radio_cmp
							checkbox_cmp
							
						} ]
				);

# Print text area with the problem


	print 	'<p>',
			$cgi -> textarea(-name=>'source',
				-default=>$display_source,
				-rows=>$Rows,
				-columns=>$Columns,
				-override =>1
				),    #-wrap=>'virtual'
			'<p>',
		$cgi -> hidden(-name => 'refreshLatex2HTML', -value => 1),
		$cgi -> hidden(-name => 'readSourceFromHTMLQ', -value => 1 ),
		'<p>',
		$cgi -> submit(-name=>'action',  -value=>'Refresh problem');
	if ($permissions == $Global::instructor_permissions) {	
		print	' ', $cgi -> submit(-name=>'action', -value=>'Save updated version');
		print	' ', $cgi -> submit(-name=>'action', -value=>'Save as'),
			$cgi -> textfield(-name=>'new file name', -size => 40, -value=> "$probFileName"),
			'<br>For &quot;Save as&quot;, choose a new file name.';		
	}
	print "\r\n",$cgi -> endform(),"\r\n","\r\n",;
	print
	    "\r\n",
		$cgi -> startform(-action=>"$Global::problemEditor_CGI"),
		"\r\n",
		$cgi -> hidden(-name=>'probNum', -value=>$probNum),
		$cgi -> hidden(-name=>'probSetKey', -value=>$psvn),
# get course, user, key
		&sessionKeyInputs(\%inputs),
		$cgi -> hidden(-name=>'Mode',	-value=>'HTML'),
		$cgi -> hidden(-name=>'seed',	-value=>$seed),
		hidden(-name=>'source', -value=>$source),
		$cgi -> submit(-name=>'action', -value=>'Revert to original and Resize window'),
		'  Rows: ',
		$cgi -> textfield(-name=>'Rows', -default=>$Rows, -size => 3),
		'  Columns: ',
		$cgi -> textfield(-name=>'Columns', -default=>$Columns, -size => 3),

		"\r\n",,
		$cgi -> endform(),

		&htmlBOTTOM($0, \%inputs);


# begin Timing code
if( $main::logTimingData == 1 ) {
	my $endTime = new Benchmark;
	&Global::logTimingInfo($main::beginTime,$endTime,'problemEditor.pl',$Course,$User);
}
# end Timing code

exit;

###############################
##subroutines

##this subroutine is from processProblem
##why is it called processProblem_htmlTOP?  is there a generic htmlTOP?
sub processProblem_htmlTOP {
		my ($title, $bg_url) = @_;
		my $background_url = $bg_url || $Global::background_plain_url;
		#my $out =  header(-type=>'text/html');
		my $out = <<EOF;
Content-type: text/html


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"  "http://www.w3.org/TR/REC-html40/strict.dtd">


EOF

		$out .=	start_html(-'title'=>$title,
				-background=>$background_url);

	$out;
}
sub decodeSource {
	my $source = shift;
	warn "Only source embedded in HTML needs to be decoded" unless defined($inputs{'source'});
	if ( defined($inputs{'source_encoded_using'}) ) {  # the source has been encoded and we need to decode it first
		if ( $inputs{'source_encoded_using'} eq 'base64_encode' )  {
			$source = decode_base64($source); 
		} 
		elsif ( $inputs{'source_encoded_using'} eq 'cgi_escape' ) {
			$source = $cgi -> unescape($source);
		}
		elsif ( $inputs{'source_encoded_using'} eq 'none'  )    {
		  # no action needed
		}
		elsif ( $inputs{'source_encoded_using'} eq 'escaped_returns'  )    {
		  $source =~s/&#010;/\n/g;  warn "uncoding escaped returns";
		  $source =~s/\r\n/\n/g;
		}
		else {
			warn "Did not recognize the source encoding method $inputs{'source_encoded_using'}";
		}
	 }
     $source;
}

##Subroutine saveProblem takes the modified source of the problem and
##saves it to the file with the original problem name and appends the
##old version of the problem to the file problemname.pg.bak
# sub saveProblem {
# 	my ($source, $probFileName)= @_;
# 	my $org_source;
# 	##get original source of the problem
# 	if (-e "${templateDirectory}$probFileName" ) {
# 		unless (-r "${templateDirectory}$probFileName") {
# 			wwerror($0, "Can't read ${templateDirectory}$probFileName");
# 		}
# 		open(PROB,"<${templateDirectory}$probFileName");
# 		$org_source = join("",<PROB>);
# 			close(PROB);
# 	} else {
# 		wwerror($0, "<H4>Error: The problem ${templateDirectory}$probFileName could not be found!</H4>");
#  	}
# 	##append old version to problemfilename.pg.bak:
# 	open BAKFILE, ">>${templateDirectory}${probFileName}.bak" or
# 		wwerror($0, "Could not open ${templateDirectory}${probFileName}.bak for appending.");
# 	my ($sec, $min, $hour, $mday, $mon, $year)=localtime(time);
# 	print BAKFILE "##################################################################\n",
# 		"##########Date:: $mday-$mon-$year, $hour:$min:$sec#########", "\n\n\n";
# 	print BAKFILE $org_source;
# 	close BAKFILE;
# 	chmod 0660, "${templateDirectory}${probFileName}.bak";
# 	##copy new version to the file problemfilename.pg
# 	open PROBLEM, ">${templateDirectory}$probFileName" or die
# 		wwerror($0, "Could not open ${templateDirectory}$probFileName for writing.
# 		Check that the  permissions for this problem are 660 (-rw-rw----)");
# 	print PROBLEM $source;
# 	close PROBLEM;
# 	chmod 0660, "${templateDirectory}${probFileName}";
#
# }

