<?php
//check that angle brackets are balanced
function bracketbalance($line)
{
	#first, if no angle brackets, we're OK
	if(substr_count($line, "<") == 0 &&  substr_count($line, ">") == 0)
		return true;

	if(substr_count($line, "<") != substr_count($line, ">"))
	{
		return false;
	}

	return true;
}

// Retrieve transcript for this strip from the database, modifying the strip object.
function gettranscript(&$strip)
{
	global $dbConnection;

	$result = $dbConnection->executeQuery('SELECT strip FROM transcript WHERE strip = ?', array($strip->id));

	if($result)
	{
		$output = '';
		/*
		#this gets me the highest panel number that has a transcript
		# panels beyond that either lack speech or don't exist
		# either way, I care not
		Might be able to exchange this loop of getOne()s for a getAll() call.
		*/
		$numPanels = $dbConnection->fetchColumn('SELECT MAX(panel) FROM transcript WHERE strip = ?', array($strip->id));
		if( $numPanels ) {
			for($i = 1; $i <= $numPanels; $i++) {
				$result = $dbConnection->executeQuery('SELECT speaker, speech FROM transcript WHERE transcript.strip = ? AND panel = ? ORDER BY line', array($strip->id, $i))
					or mtdie("There was an error fetching the panel count in the transcript for $strip->id, panel $i. " . $dbConnection->errorCode(), 'SQL Error');

				if(!$result) continue;

				$output.= "\nnewpanel\n";
				while($row = $result->fetch(PDO::FETCH_NUM)) {
					if(strlen($row[0]) < 1) continue;

					$output.= $row[0];
					if($row[1] !== '') $output.= ":: ".$row[1];
					$output.= "\n";
				}
			}
		}
	}
	$strip->transcript = $output;
	return $output;
}


// Parse submitted transcript from strip object, and insert it into the database.
function savetranscript( &$strip ) {
	global $dbConnection;
	$info = '';

	$dbConnection->beginTransaction();

	//remove any old transcript data - it's being replaced
	$dbConnection->executeUpdate('DELETE FROM transcript WHERE transcript.strip = ?', array($strip->id));

	if( $strip->transcript_posted ) {
		$inserter = 'INSERT INTO transcript (strip, panel, line, speaker, speech, search) VALUES (?, ?, ?, ?, ?, ?)';
		$inserter_types = array(PDO::PARAM_INT, PDO::PARAM_INT, PDO::PARAM_INT, PDO::PARAM_STR, PDO::PARAM_STR, PDO::PARAM_STR);

		if(strpos($strip->transcript_posted, 'Panel <$n>') !== FALSE) {
			# This is probably a scrivener script

			$panels = explode('Panel <$n>', $strip->transcript_posted);
			$panels = array_map('trim', $panels);
			$numPanels = count($panels);

			for($i = 0; $i < $numPanels; $i++) {
				$lines = explode("\n", $panels[$i]);
				$lines = array_map('trim', $lines);

				# Initialize speaker controls
				$speaker = null;
				$has_spoken = true;

				for($j = 0; $j < count($lines); $j++) {
					$inserter_values = array();

					if(strpos($lines[$j], '(') === 0) {
						# Line is a note, add it as a comment
						$inserter_values = array($strip->id, $i, $j, '#', $lines[$j], '');
					} elseif(strpos($lines[$j], '[') === 0 || strlen($lines[$j]) == 0) {
						# Line is an annotation or blank, do nothing
						continue;
					} elseif(strpos($lines[$j], 'nospeaking:') === 0) {
						# Line contains a list of nonspeaking characters
						array_splice($lines, $j, 1, array_map('_nospeaker', explode(',', substr($lines[$j], 11))));
						$speaker = trim(substr($lines[$j], 11));
						$inserter_values = array($strip->id, $i, $j, $speaker, '', '');
					} elseif($i > 0 && $lines[$j] == strtoupper($lines[$j])) {
						# Line designates a new speaker, note speaker

						# Handle speakers who did not say anything
						if(null !== $speaker && !$has_spoken)
							$inserter_values = array($strip->id, $i, $j, $speaker, '', '');

						$speaker = ucfirst(strtolower($lines[$j]));
						$has_spoken = false;
					} elseif(null !== $speaker) {
						# Line is speech, match with speaker and add
						if(!bracketbalance($lines[$j]))
							$info .= "<p>Warning: Open brackets do not match close brackets in panel $i for speaker ".htmlentities($speaker).'</p>';

						$search = preg_replace( '/[[:punct:]]|(?<=\s)\s+/', ' ', strtolower($lines[$j]) );
						$inserter_values = array($strip->id, $i, $j, $speaker, $lines[$j], $search);
						$has_spoken = true;
					} else {
						# Line is unrecognized, add it as a comment
						$inserter_values = array($strip->id, $i, $j, '#', $lines[$j], '');
					}

					if( $inserter_values && false === $dbConnection->executeUpdate($insert_sql, $inserter_values, $inserter_types) ) {
						$dbConnection->rollback();
						mtdie ($dbConnection->errorCode(), 'Error inserting transcript.');
					}
				}

				if(null !== $speaker && !$has_spoken) {
					$inserter_values = array($strip->id, $i, $j, $speaker, '', '');
					if( false === $dbConnection->executeUpdate($insert_sql, $inserter_values, $inserter_types) ) {
						$dbConnection->rollback();
						mtdie ($dbConnection->errorCode(), 'Error inserting transcript.');
					}
				}
			}

		} else {
			# Assume that this is a Kalium style transcript

			$panels = explode('newpanel', $strip->transcript_posted);
			$numPanels = count($panels);
			foreach($panels as $currPanel)
				$currPanel = trim($currPanel);

			for($i = 1; $i < $numPanels; $i++) {
				$lines = explode("\n", $panels[$i]);
				$numLines = count($lines);
				foreach($lines as $currLine)
					$currLine = trim($currLine);

				for($j = 1; $j < $numLines; $j++) {
					$spoken = explode("::", $lines[$j]); // Distinguish between speaker and speech

					$spoken[0] = trim($spoken[0]);	// Strip excess whitespace
					$spoken[1] = trim($spoken[1]);

					if(strlen($spoken[0]) <  1) continue;	// Disregard null
					$spoken[2] = preg_replace('/[[:punct:]]|(?<=\s)\s+/', ' ', strtolower($spoken[1]) );	// Make searchable text

					if(!bracketbalance($spoken[1]))
						$info .= "<p>Warning: Open brackets do not match close brackets in panel $i for speaker ".htmlentities($spoken[0]).'</p>';

					$inserter_values = array($strip->id, $i, $j, $spoken[0], $spoken[1], $spoken[2]);
					if( false === $dbConnection->executeUpdate($insert_sql, $inserter_values, $inserter_types) ) {
						$dbConnection->rollback();
						mtdie ($dbConnection->errorCode(), 'Error inserting transcript.');
					}
				}
			}
		}
	}
	$dbConnection->commit();
	return $info;
}

function _nospeaker($name)
{
	return "nospeaking: $name";
}

?>
