<?php

class Tapatalk_BbCode_Formatter_Tapatalk extends XenForo_BbCode_Formatter_Base
{

	protected $returnHtml = true;

	protected $_simpleReplacements = array(
		'left' => "%s\n",
		'center' => "%s\n",
		'indent' => "    %s\n",
		'right' => "%s\n"
	);

	protected $_advancedReplacements = array(
		'code' => array('$this', 'handleTagCode'),
		'php' => array('$this', 'handleTagPHP'),
		'html' => array('$this', 'handleTagHtml'),
		'quote' => array('$this', 'handleTagQuote'),
		'img' => array('$this', 'renderTagUnparsed'),
		'url' => array('$this', 'handleTagUrl'),
		'tex' => array('$this', 'handleTagTex'),
		'attach' => array('$this', 'handleTagAttach'),
		'media' => array('$this', 'handleTagMedia'),
		'list' => array('$this', 'handleTagList'),
		'spoiler' => array('$this', 'handleTagSpoiler'),
        'color' => array('$this', 'handleTagColor'),
	);

	protected $_ttMediaSites = array(
		'youtube' => 'http://www.youtube.com/watch?v={$id}',
		'vimeo' => 'http://www.vimeo.com/{$id}',
		'facebook' => 'http://www.facebook.com/video/video.php?v={$id}',
        'twitter' => 'https://twitter.com/m/status/{$id}',
	    'tweet' => 'https://twitter.com/m/status/{$id}',
	);

	public function __construct($returnHtml = false)
	{
        $this->_returnHtml = $returnHtml;
		$this->_tags = $this->getTags();
		$this->preLoadData();
        if(false)
        {
            $options = array();
            if (XenForo_Application::isRegistered('smilies'))
            {
                $options['smilies'] = XenForo_Application::get('smilies');
            }
            else
            {
                $options['smilies'] = XenForo_Model::create('XenForo_Model_Smilie')->getAllSmiliesForCache();
                XenForo_Application::set('smilies', $options['smilies']);
            }
            if ($options['smilies'])
            {
                $this->addSmilies($options['smilies']);
            }
        }
	}
    /**
     * Add the specified list of smilies to the list that will be processed.
     *
     * @param array $smilies List of smilies with data from the DB (smilie_id, smilieText [array], image_url)
     */
	public function addSmilies(array $smilies)
	{
        $this->_smilieTemplate = '<img src="%1$s?ttinline=true" class="mceSmilie" alt="%2$s" title="%3$s    %2$s" />';
        foreach ($smilies AS $smilie)
		{

			foreach ($smilie['smilieText'] AS $text)
			{
				$this->_smilieTranslate[$text] = "\0" . $smilie['smilie_id'] . "\0";
			}

			if (empty($smilie['sprite_params']))
			{
                if(strpos($smilie['image_url'],'http') !== 0)
                {
                    $smilie['image_url'] = XenForo_Link::convertUriToAbsoluteUri($smilie['image_url'], true);
                }
				$this->_smilieReverse[$smilie['smilie_id']] = $this->_processSmilieTemplate($smilie);
			}
			else
			{
                $pathInfo = pathinfo($smilie['image_url']);
                $fileName =  $pathInfo['filename'] . '_' . ($smilie['sprite_params']['x'] * -1) . '_' . $smilie['sprite_params']['y'] . '_' . ($smilie['sprite_params']['w'] * -1). '_' . $smilie['sprite_params']['h'] . '.png';
                $options = XenForo_Application::get('options');
                $mobiquoSmiliePath = SCRIPT_ROOT . $options->tp_directory . '/smilies/';
                try
                {
                    if(!file_exists($mobiquoSmiliePath . $fileName))
                    {
                        if(is_writeable($mobiquoSmiliePath))
                        {
                            // Create image instances
                            if($pathInfo['extension'] == 'png')
                            {
                                $src = imagecreatefrompng($smilie['image_url']);
                            }
                            else
                            {
                                $src = imagecreatefromgif($smilie['image_url']);
                            }
                            $dest = imagecreate($smilie['sprite_params']['w'], $smilie['sprite_params']['h']);

                            // Copy
                            imagecopy($dest, $src, 0, 0, $smilie['sprite_params']['x'] * -1, $smilie['sprite_params']['y']*-1, $smilie['sprite_params']['w'], $smilie['sprite_params']['h']);

                            imagepng($dest, $mobiquoSmiliePath . $fileName);
                        }
                    }
                }
                catch(Exception $ex){}
                $smilie['image_url'] = $options->tp_directory . '/smilies/' . $fileName;
                if(strpos($smilie['image_url'],'http') !== 0)
                {
                    $smilie['image_url'] = XenForo_Link::convertUriToAbsoluteUri($smilie['image_url'], true);
                }
                $this->_smilieReverse[$smilie['smilie_id']] = $this->_processSmilieTemplate($smilie);

                //$this->_smilieReverse[$smilie['smilie_id']] = $this->_processSmilieSpriteTemplate($smilie);
			}

			$this->_smiliePaths[$smilie['image_url']] = $smilie['smilie_id'];
		}
	}
	public function getTags()
	{
		if ($this->_tags !== null)
		{
			return $this->_tags;
		}

		$callback = array($this, 'handleTag');

		$tags = parent::getTags();
		$tags['tex'] = array(
			'hasOption' => false,
			'plainChildren' => false
		);

		foreach ($tags AS $tagName => &$tag)
		{
			if($this->_returnHtml){
				switch($tagName){
					case 'b':
					case 'i':
						break;
					case 'u':
						$tag['replace'] = array('<u>', '</u>');
						break;
					case 'color':
						$tag['replace'] = array('<font color="%s">', '</font>');
                    case 'img':
                        break;
					default:
						unset($tag['replace'], $tag['callback']);
						$tag['callback'] = $callback;
						break;
				}
			} else {
                switch($tagName){
					case 'img':
                        break;
					default:
						unset($tag['replace'], $tag['callback']);
						$tag['callback'] = $callback;
						break;
                }
            }
		}
		return $tags;
	}

	public function renderTagImage(array $tag, array $rendererStates)
	{
		$url = $this->stringifyTree($tag['children']);

		$validUrl = $this->_getValidUrl($url);
		if (!$validUrl)
		{
			return $this->filterString($url, $rendererStates);
		}

		$censored = XenForo_Helper_String::censorString($validUrl);
		if ($censored != $validUrl)
		{
			return $this->filterString($url, $rendererStates);
		}

		// attempts to convert smilies posted as [IMG] tags back into smilies
		if ($rendererStates['imgToSmilie'])
		{
			foreach ($this->_smiliePaths AS $smiliePath => $smilieId)
			{
				if (strpos($url, $smiliePath) !== false && substr($url, strlen($smiliePath) * -1) == $smiliePath)
				{
					return $this->_smilieReverse[$smilieId];
				}
			}
		}

		if ($rendererStates['disableProxying'])
		{
			$imageUrl = $validUrl;
		}
		else
		{
            $imageUrl = XenForo_Link::convertUriToAbsoluteUri($this->_handleImageProxyOption($validUrl, $rendererStates), true);
		}
        return '[img]' . $imageUrl . '[/img]';
	}
	public function handleTagUrl(array $tag, array $rendererStates)
	{
		if (!empty($tag['option']))
		{
			$url = $tag['option'];
			$text = $this->renderSubTree($tag['children'], $rendererStates);
		}
		else
		{
			$url = $this->stringifyTree($tag['children']);
			$text = urldecode($url);
			if (!utf8_check($text))
			{
				$text = $url;
			}
			$text = XenForo_Helper_String::censorString($text);

			if (!empty($rendererStates['shortenUrl']))
			{
				$length = utf8_strlen($text);
				if ($length > 100)
				{
					$text = utf8_substr_replace($text, '...', 35, $length - 35 - 45);
				}
			}

			$text = htmlspecialchars($text);
		}

		$url = $this->_getValidUrl($url);
		if (!$url)
		{
			return $text;
		}
		else
		{
			$url = XenForo_Helper_String::censorString($url);

			return "[url={$url}]{$text}[/url]";
		}
	}

	public function handleTagTex(array $tag, array $rendererStates)
	{
		$tex = $this->stringifyTree($tag['children']);
        $tex = urlencode($tex);
		$url = "http://latex.codecogs.com/gif.latex?{$tex}";
		return "[img]{$url}[/img]";
	}

	public function filterString($string, array $rendererStates)
	{
		$string = XenForo_Helper_String::censorString($string);
        if (false && empty($rendererStates['stopSmilies']))
		{
            $string = $this->replaceSmiliesInText($string);
		}
		return $string;
	}

	public function handleTagMedia(array $tag, array $rendererStates)
	{
		$mediaKey = trim($this->stringifyTree($tag['children']));
		if (preg_match('#[&?"\'<>]#', $mediaKey) || strpos($mediaKey, '..') !== false)
		{
			return '';
		}

		$mediaSiteId = strtolower($tag['option']);
		if (isset($this->_ttMediaSites[$mediaSiteId]))
		{
			$embedHtml = $this->_ttMediaSites[$mediaSiteId];
			return "[url]".str_replace('{$id}', urlencode($mediaKey), $embedHtml)."[/url]";
		}
		else
		{
			return "Unsupported video ([media={$mediaSiteId}]{$mediaKey}[/media])";
		}
	}


	public function handleTag(array $tag, array $rendererStates)
	{
		$tagName = $tag['tag'];

		if (isset($this->_advancedReplacements[$tagName]))
		{
			$callback = $this->_advancedReplacements[$tagName];
			if (is_array($callback) && $callback[0] == '$this')
			{
				$callback[0] = $this;
			}

			return call_user_func($callback, $tag, $rendererStates);
		}

		$output = $this->renderSubTree($tag['children'], $rendererStates);

		if (isset($this->_simpleReplacements[$tagName]))
		{
			$output = sprintf($this->_simpleReplacements[$tagName], $output);
		}

		return $output;
	}

	public function handleTagAttach(array $tag, array $rendererStates)
	{
		$id = intval($this->stringifyTree($tag['children']));
		if (!$id)
		{
			return '';
		}

		if (empty($rendererStates['attachments'][$id]))
		{
            try
            {
                $attachmentModel = XenForo_Model::create('XenForo_Model_Attachment');
                $attachment = $attachmentModel->getAttachmentById($id);
            }
            catch(Exception $ex){}
            if(!isset($attachment))
            {
                $attachment = array('attachment_id' => $id);
            }
			$validAttachment = false;
			$canView = false;
		}
		else
		{
			$attachment = $rendererStates['attachments'][$id];
			$validAttachment = true;
			$canView = empty($rendererStates['viewAttachments']) ? false : true;
		}
		if(!$validAttachment){

			$output = "[url=".XenForo_Link::convertUriToAbsoluteUri(XenForo_Link::buildPublicLink('attachments', $attachment), true)."]".
			new XenForo_Phrase('view_attachment_x', array('name' => $attachment['attachment_id']))."[/url]";

		} elseif(empty($attachment['thumbnailUrl'])){

			$output = "[url=".XenForo_Link::convertUriToAbsoluteUri(XenForo_Link::buildPublicLink('attachments', $attachment), true)."]".
			new XenForo_Phrase('view_attachment_x', array('name' => $attachment['filename']))."[/url]";

		} elseif($canView && strtolower($tag['option']) == 'full'){

			$output = "[img]".XenForo_Link::convertUriToAbsoluteUri(XenForo_Link::buildPublicLink('attachments', $attachment), true)."[/img]";

		} elseif($canView){

			/*$output = "[url=".XenForo_Link::convertUriToAbsoluteUri(XenForo_Link::buildPublicLink('attachments', $attachment, array('embedded' => '1')), true)."][img]".
			XenForo_Link::convertUriToAbsoluteUri($attachment['thumbnailUrl'], true)."[/img][/url]";*/
			$output = "[img]".XenForo_Link::convertUriToAbsoluteUri(XenForo_Link::buildPublicLink('attachments', $attachment), true)."[/img]";

		} else {

			/*$output = "[url=".XenForo_Link::convertUriToAbsoluteUri(XenForo_Link::buildPublicLink('attachments', $attachment), true)."][img]".
			XenForo_Link::convertUriToAbsoluteUri($attachment['thumbnailUrl'], true)."[/img][/url]";      */
			/*$output = "[img]".XenForo_Link::convertUriToAbsoluteUri(XenForo_Link::buildPublicLink('attachments', $attachment), true)."]".
			new XenForo_Phrase('view_attachment_x', array('name' => $attachment['filename']))."[/url]";*/
            $output = "[img]".XenForo_Link::convertUriToAbsoluteUri(XenForo_Link::buildPublicLink('attachments', $attachment), true)."[/img]";
		}

		return $output;
	}

	public function handleTagList(array $tag, array $rendererStates)
	{
		$bullets = explode('[*]', trim($this->renderSubTree($tag['children'], $rendererStates)));

		$output = "\n";
		foreach ($bullets AS $bullet)
		{
			$bullet = trim($bullet);
			if ($bullet !== '')
			{
				$output .= " - ".$bullet . "\n";
			}
		}
		$output .= "\n";

		return $output;
	}

	public function handleTagQuote(array $tag, array $rendererStates)
	{
		if (empty($rendererStates['quoteDepth']))
		{
			$rendererStates['quoteDepth'] = 1;
		}
		else
		{
			$rendererStates['quoteDepth']++;
		}
/*
		if ($this->_maxQuoteDepth > -1 && $rendererStates['quoteDepth'] > $this->_maxQuoteDepth)
		{
			return '';
		}*/

		if ($tag['option'])
		{
			$parts = explode(',', $tag['option']);
			$name = $this->filterString(array_shift($parts), $rendererStates);

			$tag['option'] = '';
			$tag['original'][0] = '[quote]';
		}
		else
		{
			$name = false;
		}

		if (!empty($tag['original']) && is_array($tag['original']))
		{
			list($prepend, $append) = $tag['original'];
		}
		else
		{
			$prepend = '';
			$append = '';
		}

		if(!empty($name)){
			$prepend_referer = new XenForo_Phrase('x_said', array('name' => $name)).": ";

			if (isset($rendererStates['returnHtml']) && $rendererStates['returnHtml'])
				$prepend .= "<b>{$prepend_referer}</b><br />";
			else
				$prepend .= "$prepend_referer\r\n";
		}

/*
		if ($rendererStates['quoteDepth'] == $this->_maxQuoteDepth)
		{
			// at the edge of the quote, so we want to ltrim whatever comes after
			foreach ($tag['children'] AS $key => $child)
			{
				if (is_array($child) && !empty($child['tag']) && $child['tag'] == 'quote' && isset($tag['children'][$key + 1]))
				{
					$after =& $tag['children'][$key + 1];
					if (is_string($after))
					{
						$after = ltrim($after);
					}
				}
			}
		}

		if ($this->_stripAllBbCode)
		{
			$prepend = '';
			$append = '';
		}*/

		return $this->filterString($prepend, $rendererStates)
			. $this->renderSubTree($tag['children'], $rendererStates)
			. $this->filterString($append, $rendererStates);
	}

	public function handleTagCode($tag, $rendererStates){
		if ($tag['option'])
		{
			$parts = explode(',', $tag['option']);
			$name = $this->filterString(array_shift($parts), $rendererStates);

			$tag['option'] = '';
			$tag['original'][0] = '[CODE]';
		}
		else
		{
			$name = false;
		}

		if (!empty($tag['original']) && is_array($tag['original']))
		{
			list($prepend, $append) = $tag['original'];
		}
		else
		{
			$prepend = '';
			$append = '';
		}

		if(!empty($name)){
			$prepend_referer = new XenForo_Phrase('x_said', array('name' => $name)).": ";

			if (isset($rendererStates['returnHtml']) && $rendererStates['returnHtml'])
				$prepend .= "<b>{$prepend_referer}</b><br />";
			else
				$prepend .= "$prepend_referer\r\n";
		}

		return $this->filterString($prepend, $rendererStates)
			. $this->renderSubTree($tag['children'], $rendererStates)
			. $this->filterString($append, $rendererStates);
	}

	public function handleTagPHP($tag, $rendererStates){
		$content = $this->renderSubTree($tag['children'], $rendererStates);
		$content = preg_replace('/\[(CODE|\/CODE)\]/', "[ $1]" , $content);
		return '[CODE]'
			. $content
			. '[/CODE]';
	}

	public function handleTagHtml($tag, $rendererStates){
		$content = $this->renderSubTree($tag['children'], $rendererStates);
		$content = preg_replace('/\[(CODE|\/CODE)\]/', "[ $1]" , $content);
		return '[CODE]'
			. $content
			. '[/CODE]';
	}

	public function handleTagSpoiler($tag, $rendererStates){
		$bullets = explode('[*]', trim($this->renderSubTree($tag['children'], $rendererStates)));

		$output = "\n";
		foreach ($bullets AS $bullet)
		{
			$bullet = trim($bullet);
			if ($bullet !== '')
			{
				$output .= "[spoiler]".$bullet . "[/spoiler]\n";
			}
		}
		$output .= "\n";
		return $output;
	}

    public function handleTagColor($tag, $rendererStates){
        $content = $this->renderSubTree($tag['children'], $rendererStates);
        return '<font color="'.$tag['option'].'">'.$content.'</font>';
    }
}