<?php

error_reporting(E_ALL);
ini_set('display_errors', 'on');

$ini = json_decode(@file_get_contents(__DIR__.'/blog_options.ini'), true);
if ($ini === null) {
	die("Missing blog_options.ini\n");
}

$OPTIONS = array(
	'blogtitle'  => $ini['title'],
	'rssfile'    => 'rss-articles.xml',
	'public_url' => rtrim($ini['url'], '/').'/',
	'rssauthor'  => $ini['rss-author'],
	'template'   => $ini['template'],
	'timezone'   => $ini['timezone'],
);

date_default_timezone_set($OPTIONS['timezone']);

$template = @file_get_contents(__DIR__.'/'.$OPTIONS['template']);
if ($template === false) {
	die("Missing template.html\n");
}

$articles = array();
foreach(scandir(__DIR__.'/articles/') as $article) {
	$matches = array();
	
	if (preg_match('~(\d\d\d\d-\d\d-\d\d)-(.+)\.txt~', $article, $matches)) {
		$articles[] = array(
			'filepath' => __DIR__.'/articles/'.$article,
			'date' => $matches[1],
			'title' => str_replace('_', ' ', $matches[2])
		);
	}
}

function article_htmlname($article) {
	return $article['date'].'-'.strtolower(str_replace(' ', '_', $article['title'])).'.html';
}

// Build each page

for($i = 0, $e = count($articles); $i != $e; ++$i) {
	$article = $articles[$i];

	$previous = "&laquo; Older";
	$next = "Newer &raquo;";
	
	if ($i) {
		$previous = '<a href="'.urlencode(article_htmlname($articles[$i - 1])).'" title="'.h($articles[$i - 1]['title']).'">'.$previous.'</a>';
	}
	
	if ($i != $e - 1) {
		$next = '<a href="'.urlencode(article_htmlname($articles[$i + 1])).'" title="'.h($articles[$i + 1]['title']).'">'.$next.'</a>';
	}
	
	$content = file_get_contents($article['filepath']);
	$content_html = '<h2>'.h($article['title']).'</h2>'.displayfmt($content).'<br><br><br><em>-- Article published '.$article['date'].'</em>';
	
	$nav = $previous.' :: '.$next;
		
	$article_html = str_replace(
		array( '$article', '$title', '$nav', '$blogtitle', '$rssfile' ),
		array( $content_html, h($article['title']), $nav, h($OPTIONS['blogtitle']), h($OPTIONS['rssfile']) ),
		$template
	);
	
	$save_path = __DIR__.'/wwwroot/'.article_htmlname($article);
	
	if (file_put_contents($save_path, $article_html) === false) {
		echo "Error saving article ".$article['title']."\n";
	}
}

// Build RSS feed

$rss = '<?xml version="1.0" encoding="UTF-8" ?> 
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"> 
	<channel>
		<title>'.h($OPTIONS['blogtitle']).'</title>
		<link>'.h($OPTIONS['public_url']).'</link>
		<description>'.h($OPTIONS['blogtitle'].' - Articles').'</description>
		<language>en-GB</language>
		<atom:link href="'.h($OPTIONS['public_url'].$OPTIONS['rssfile']).'" rel="self" type="application/rss+xml" />';
			foreach($articles as $article) {
				$rss .= '
			<item>
				<title>'.h($article['title']).'</title>
				<link>'.h($OPTIONS['public_url'].article_htmlname($article)).'</link>
				<guid>'.h($OPTIONS['public_url'].article_htmlname($article)).'</guid>
				<author>'.h($OPTIONS['rssauthor']).'</author>
				<pubDate>'.h(date(DATE_RSS, filemtime($article['filepath']))).'</pubDate>
			</item>';
			}
			$rss .= '
	</channel>
</rss>';

if (file_put_contents( __DIR__.'/wwwroot/'.$OPTIONS['rssfile'], $rss) === false) {
	echo "Error saving RSS xml\n";
}

// Build index page

$article_list = '<strong>ARTICLES</strong>';
$article_datefmt = 'Y-m-d';
foreach(array_reverse($articles) as $article) {
	$pubdate = $article['date'];
	$up_date = date('Y-m-d', filemtime($article['filepath']));
	
	$article_list .= '
	<p>
		<a href="'.article_htmlname($article).'"><strong>'.h($article['title']).'</strong></a><br>
		<em>Published '.$pubdate/*.($pubdate != $up_date ? ', Updated '.$up_date : '')*/.'</em>
	</p>
	';
}

$index_html = str_replace(
	array( '$article', '$title', '$blogtitle', '$rssfile', '$nav' ),
	array( $article_list, h('Articles'), h($OPTIONS['blogtitle']), h($OPTIONS['rssfile']), ''),
	$template
);

if (file_put_contents( __DIR__.'/wwwroot/index.html', $index_html) === false) {
	echo "Error saving article index\n";
}


// All done!

die("All done!\n");

//
// Rendering engine from /wiki/index.php
// 

function h($s) {
	return htmlspecialchars($s, ENT_QUOTES, 'UTF-8');
}
	
function pregwipe($data, $s_to_r) {
	foreach($s_to_r as $s=>$r) {
		while(preg_match($s, $data)) {
			if (is_callable($r)) {$data = preg_replace_callback($s, $r, $data);
			} else {$data = preg_replace($s, $r, $data);}
		}
	}
	return $data;
}

// An embarassing cascade of half-working hacks follows.

function bbtables($string) {
	$lines  = explode("\n", $string);
	$lastct = 0;
	$ret    = array();
	$tbl    = array();
	$buffer = array();
	foreach ($lines as $line) {
		if (strlen($line) && $line[0] == '|') {
			if (count($buffer)) {
				$ret[] = bbcode(h(implode("\n",$buffer))); // SYNCHRONISE
				$buffer = array();
			}
			
			$cols = explode('|', $line);
			if ($lastct != count($cols)) {
				if ($lastct > 0) { // Close previous table
					$tbl[] = '</table>';
					$ret[] = implode('', $tbl);
					$tbl = array();
					$lastct = 0;
				}
				// Start new table
				$lastct = count($cols);
				$tbl[] = '<table class="ti">';
			}
			$cols = array_map(function($c) {
				return bbcode(h(str_replace(';',"\n",$c))); // SYNCHRONISE
			}, $cols);
			// Add these columns
			$tbl[] = '<tr><td>'.implode('</td><td>',array_slice($cols, 1)).
				'</td></tr>'
			;
		} else {
			if ($lastct > 0) {
				// Close previous table
				$tbl[] = '</table>';
				$ret[] = implode('', $tbl);
				$tbl = array();
				$lastct = 0;
			}
			$buffer[] = $line;
		}
	}
	if (count($buffer)) {
		$ret[] = bbcode(h(implode("\n",$buffer))); // SYNCHRONISE
		$buffer = array();
	}
	if ($lastct > 0) {
		$tbl[] = '</table>';
		$ret[] = implode('', $tbl);
		$lastct = 0;
	}
	return implode("\n", $ret);
}

function bbcode($string) {
	return pregwipe($string, array(
		'@\[(?i)h\](.*?)\[/(?i)h\]@si'      => '<h2>\\1</h2>',
		'@\[(?i)b\](.*?)\[/(?i)b\]@si'      => '<b>\\1</b>',
		'@\[(?i)i\](.*?)\[/(?i)i\]@si'      => '<i>\\1</i>',
		'@\[(?i)u\](.*?)\[/(?i)u\]@si'      => '<u>\\1</u>',
		'@\[(?i)s\](.*?)\[/(?i)s\]@si'      => '<span class="s">\\1</span>',
		'@\[(?i)spoiler\](.*?)\[/(?i)spoiler\]@si' => '<span class="spoiler">\\1</span>',
		'@\[(?i)img\](.*?)\[/(?i)img\]@si'  => '<img alt="" src="\\1">',
		'@\[(?i)list\](.*?)\[/(?i)list\]@si'=> '<ul><li>\\1</li></ul>',
		'@\[\*\]@si'                        => '</li><li>',
		
		'@\[(?i)url=(.*?)\](.*?)\[/(?i)url\]@si' => '<a href="\\1">\\2</a>',
		
		'@\[(?i)article=(.*?)\](.*?)\[/(?i)article\]@si' => function($m) {
			return '<a href="'.rawurlencode(strtolower($m[1])).'.html">'.$m[2].'</a>';
		},			
		
		'@\[(?i)imgur\](.*?)\.(...)\[/(?i)imgur\]@si' =>
			'<a href="http://i.imgur.com/\\1.\\2">'.
			'<img class="imgur" alt="" src="http://i.imgur.com/\\1s.\\2" >'.
			'</a>'
		,
		
		'@\[(?i)section=(.*?)](.*?)\[/(?i)section\]@si' => function($m) {
			return '<div class="section"><a class="sectionheader" href="javascript:;" onclick="ts(this);">'.$m[1].'</a><span style="display:none;">'.trim($m[2]).'</span></div>';
		},

	));
}

function codefmt($m) {
	$GLOBALS['codePresent'] = true;
	
	$match = $m[1];
	$match = preg_replace('~(/\\*.*?\\*/)~s', '<span class="code-comment">$1</span>', $match);
	
	return '<span class="code">'.str_replace("<br>\r\n","\r\n",$match).'</span>';
}

function bbformat($str) {
	$ret = preg_replace_callback(
		'@\[(?i)code\](.*?)\[/(?i)code\]@si',
		'codefmt',
		str_replace(
			array("</ul><br>\r\n<br>"),
			array('</ul><br>'),
			nl2br(bbtables($str), false) //bbtables(bbcode(h($str)))
		)
	);
	return str_replace("</pre><br>\r\n<br>", "</pre>\r\n<br>", $ret);
}

function displayfmt($string) {
	$hpos = 0; $ret = '';
	while (($spos = strpos($string, "[html]", $hpos)) !== false) {
		$ret .= bbformat(substr($string, $hpos, $spos-$hpos));
		$spos += 6;
		
		$epos = strpos($string, "[/html]", $spos);
		$ret .= '<div class="html"><a href="javascript:;" onclick="els(this, \''.xesc(substr($string, $spos, $epos-$spos)).'\');">&#x26a0; run dynamic content</a></div>';
		$hpos = $epos+7;
	}
	return $ret.bbformat(substr($string, $hpos));
}

	