<?php 
defined('C5_EXECUTE') or die("Access Denied.");

/**
 * Magic Data by John Liddiard (aka JohntheFish)
 * www.jlunderwater.co.uk, www.c5magic.co.uk
 * This software is licensed under the terms described in the concrete5.org marketplace.
 * Please find the add-on there for the latest license copy.
 */

/*
The files of terms and curses are adapted from a wide range of sources
(can the authors own such terms?)
http://www.brethrenofthegreatlakes.com/pirateslang.htm
http://phrontistery.info/nautical.html
https://en.wikipedia.org/wiki/Glossary_of_nautical_terms
http://dougal.gunters.org/blog/2004/08/30/text-filter-suite (GPL)
http://www.splitbrain.org/plugin:pirate (derived from above, so also GPL)
http://www.yarr.org.uk/talk/
*/

class PirateSpeakHelper {

	public function __construct(){
		if (!is_array($this->curses)){
			$this->yer_setup();
		}	
	}

	/*
	Translate text, leaving tags alone. By default will also process Magic Data if MD is installed.
	Set $md to false if Magic Data processing is not required.
	*/
	public function yarr($text, $md=true){
		try{
			if($md && is_object($this->mdeh)){
				$text1 = $this->mdeh->fill($text);
				$text2 = preg_replace_callback('/(?(?<=>)|\A)([^<>]+)(?(?=<)|\Z)/s',
												array('PirateSpeakHelper','yer_tounges_n_curses'),
												$text1);			
			} else {
		
				$text2 = preg_replace_callback('/(?(?<=>)|\A)([^<>]+)(?(?=<)|\Z)/s',
												array('PirateSpeakHelper','yer_tounges_n_curses'),
												$text);
			}
		} catch (Exception $e){
			return $text;
		}
		if (empty($text2)) {
			return $text;
		}
		return $text2;
	}

	/*
	DOM parser version of above, left in for posterity. 
	BUT it mangles extended characters, so would need some work
	if anyone wants to develop further...
	http://stackoverflow.com/questions/10950741/replace-a-string-with-another-in-html-but-no-in-html-tags-and-attributes-php
	http://stackoverflow.com/questions/3577641/how-to-parse-and-process-html-xml
	*/
	public function aye($text){
		try{
			$d = new DOMDocument;
			$d->loadHTML($text);

			$x = new DOMXPath($d);
			foreach ($x->query('//text()') as $node) {
				$node->nodeValue = $this->yer_tounges_n_curses($node->nodeValue);
			}
			$text2 = $d->saveHTML();
		} catch (Exception $e){
			return $text;
		}
		if (empty($text2)) {
			return $text;
		}
		return $text2;
	}


    /*
    Translate a plain text fragment (no enclosed html)
    */
    function yer_tounges_n_curses($text) {
    	if (is_array($text)){
    		$text = $text[0];
    	}

       // tranlate
        $text = preg_replace($this->from,$this->to,$text);
 
 		// Insert random curses
 		return preg_replace_callback(	'/([\.!\?]\s)/s',
 										array('PirateSpeakHelper','yer_curses'),
 										$text
 									);
    }

    /*
    Attach random curses
    */
	function yer_curses($m) {
		$text = $m[0];
		$p=3; // 1 in 3
		if (preg_match('/[\?\!]\s$/',$text)){
			$p=2; // 1 in 2
		}
		if (rand(0,$p)>1){
			return $text;
		}

		// cycle curses
		$curse = array_shift($this->curses);
		$this->curses[] = $curse;

		return preg_replace("/\@X\@Y\@Z/",$text, $curse).' ';
    }

	
	/*
	Load from files
	*/
	public function yer_setup(){
	
		$md_pkg  = Package::getByHandle('jl_magic_data');
		if (is_object($md_pkg)){
			$this->mdeh = Loader::helper('md_evaluate', 'jl_magic_data');
		}
	
		if (is_array($this->curses)){
			return;
		}	

		$yer_files = DIR_PACKAGES.'/jl_pirate_speak/files/';
		$fh = Loader::helper('file');
		$yer_tounges = '';
		if(!defined('YER_TOUNGES') || (YER_TOUNGES && YER_TOUNGES !== 'false')){
			$yer_tounges .= "\n".$fh->getContents($yer_files.'yer_tounges.txt');
		}
		// site specific translations
		if(defined('YER_PORT_TOUNGES')){
			try{
				$more_tounges = $fh->getContents(YER_PORT_TOUNGES);
			} catch (Exception $e) {
				Log::addEntry($e, 'yer_port_tounges');
			}
			if ($more_tounges){
				$yer_tounges .= "\n".$more_tounges;
			}
		}

		$lines = preg_split("/\s*\n+/",$yer_tounges);
		$translations = array();
		// upper and lower case variants or regexes
		foreach ($lines as $line){
			$line = trim($line);
			if (empty($line)){
				continue;
			}
			list($k, $v) = preg_split("/\s*\:\s*/",$line);
			$k = trim($k);
			$v = trim($v);
			if (empty($k) || empty($v)){
				continue;
			}
			$translations["/\b".ucfirst($k)."([s0-9]*)\b/s"] = ucfirst($v).'$1';
			$translations["/\b".$k."([s0-9]*)\b/s"] = $v.'$1';
		}

		// has to be in reverse, so longer terms are translated first
		krsort($translations);

		// some endings
		if(!defined('YER_ENDINS') || (YER_ENDINS && YER_ENDINS !== 'false')){
			$translations['/ing\b/s'] = "in'";
			$translations['/ings\b/s'] = "in's";
			$translations['/tion\b/s'] = "shun";
			$translations['/ent\b/s'] = "en'";
			$translations['/\binter/s'] = "inner";
		}

        // Extract the keys/values:
        $this->from = array_keys($translations);
        $this->to = array_values($translations);

		// A list of curses
		$yer_curses = '';
		if(!defined('YER_CURSES') || (YER_CURSES && YER_CURSES !== 'false')){
			$yer_curses .= "\n".$fh->getContents($yer_files.'yer_curses.txt');
		}
		// site specific curses
		if(defined('YER_PORT_CURSES')){
			try{
				$more_curses = $fh->getContents(YER_PORT_CURSES);
			} catch (Exception $e) {
				Log::addEntry($e, 'yer_port_curses');
			}
			if ($more_curses){
				$yer_curses .= "\n".$more_curses;
			}
		}

		$this->curses = array_filter(preg_split("/\s*\n+/",$yer_curses));
		shuffle($this->curses);
	}


}