<?php

include_once($UTIL_DIR . "/convert.php");
include_once($UTIL_DIR . "/threads.php");
include_once($UTIL_DIR . "/parser.php");

class Post {
	public $pid;
	public $user;
	public $title;
	public $date;
	public $message;
	public $replies = array();

	public function write($fp, $indent)
	{
		fwrite($fp, $indent . "<post pid=\"" . $this->pid . "\"\n");
		fwrite($fp, $indent . "      user=\"" . $this->user . "\"\n");
		fwrite($fp, $indent . "      title=\"" . convert_xml($this->title) . "\"\n");
		fwrite($fp, $indent . "      date=\"" . $this->date . "\">\n");
		fwrite($fp, $indent . "  <message>" . convert_xml($this->message) . "</message>\n");

		foreach($this->replies as $reply) {
			$reply->write($fp, $indent . "  ");
		}
		
		fwrite($fp, $indent . "</post>\n");
	}

	public function add($post) {
		$key = $post->pid;
		$this->replies[$key] = $post;
	}

	public function getPost($pid)
	{
		$result = false;

		foreach($this->replies as $post) {
			if($post->pid == $pid) return $post;
			$result = $post->getPost($pid);
			if($result) return $result;
		}

		return $result;
	}

	public function show($indent = "    ", $recurse = true)
	{
		global $users, $fid, $tid, $current_user, $client_is_mobile_device;
		$user = $users->getUser($this->user);

		echo $indent . "<div class=\"post\">\n";
		if($client_is_mobile_device) {
			$avatar = "mobileavatar.gif";
		} else {
			if($user->avatar) $avatar = $user->avatar;
			else $avatar = "default.gif";
		}
		echo $indent . "  <img class=\"avatar\" alt=\"avatar\" src=\"gfx/avatars/" . $avatar . "\"/>\n";
		if(!$client_is_mobile_device) {
			echo $indent . "  <div class=\"id\">ID: " . $this->pid . "</div>\n";
			echo $indent . "  <div class=\"title\">Title: " . convert_xml($this->title) . "</div>\n";
		}
		echo $indent . "  <div class=\"user\">";
		if(!$client_is_mobile_device) echo "UserID: ";
		echo $user->name . "</div>\n";
		echo $indent . "  <div class=\"date\">";
		if(!$client_is_mobile_device) echo "Date: ";
		echo date("j. M Y - G:i", $this->date) . "</div>\n";
		echo $indent . "  <div class=\"message\">\n";
		echo parse($this->message, $indent . "    ") . "\n";
		if(trim($user->signature) != "") {
			echo $indent . "    <div class=\"signature\">\n";
			echo parse("--------------------------\n" . $user->signature, $indent . "      ") . "\n";
			echo $indent . "    </div>\n";
		}
		echo $indent . "  </div>\n";
		echo $indent . "  <div class=\"buttons\">\n";

		if($current_user->uid == $this->user) {
			echo $indent .
				"    <a href=\"?mode=editor&amp;task=edit&amp;fid=".$fid.
				"&amp;tid=".$tid.
				"&amp;pid=".$this->pid."\">";
			echo "<img alt=\"edit\" src=\"gfx/btn_edit.gif\"/></a>\n";
		}

		echo $indent .
			"    <a href=\"?mode=editor&amp;task=quote&amp;fid=".$fid.
			"&amp;tid=".$tid.
			"&amp;pid=".$this->pid."\">";
		echo "<img alt=\"quote\" src=\"gfx/btn_quote.gif\"/></a>\n";

		echo $indent .
			"    <a href=\"?mode=editor&amp;task=reply&amp;fid=".$fid.
			"&amp;tid=".$tid.
			"&amp;pid=".$this->pid."\">";
		echo "<img alt=\"reply\" src=\"gfx/btn_reply.gif\"/></a>\n";

		echo $indent . "  </div>\n";
		echo $indent . "  <div class=\"replies\">\n";

		if($recurse) {
			foreach($this->replies as $reply) {
				$reply->show($indent . "    ");
			}
		}

		echo $indent . "  </div>\n";
		echo $indent . "</div>\n";
	}

	public function Post($pid, $title, $user, $date, $message = "")
	{
		$this->pid = $pid;
		$this->title = $title;
		$this->user = $user;
		$this->date = $date;
		$this->message = $message;
	}
}

class Posts {
	private $file;
	private $posts = array();
	public $thread;
	private $posts_linear = array();
	private $maxkey = 0;
	
	public function nextkey() {
		$this->maxkey++;
		return $this->maxkey;
	}

	public function add($post) {
		$key = $post->pid;
		$this->posts[$key] = $post;
	}
	
	public function write()
	{
		$fp = fopen($this->file, "w");

		$block = TRUE;
		flock($fp, LOCK_EX, $block); // do an exclusive lock

		fwrite($fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");

		if($this->thread->lastseen) {
			foreach($this->thread->lastseen as $key => $value) {
				if($lastseenstr != "") $lastseenstr .= ",";
				$lastseenstr .= $key . "=" . $value;
			}
		}

		fwrite($fp, "<thread tid=\"" . $this->thread->tid . "\"\n");
		fwrite($fp, "        name=\"" . convert_xml($this->thread->name) . "\"\n");
		fwrite($fp, "        lastpost=\"" . $this->thread->lastpost . "\"\n");
		fwrite($fp, "        lastseen=\"" . $lastseenstr . "\">\n");

		foreach($this->posts as $post) {
			$post->write($fp, "  ");
		}

		fwrite($fp, "</thread>\n");

		fclose($fp);
	}

	public function getPost($pid)
	{
		$result = false;

		foreach($this->posts as $post) {
			if($post->pid == $pid) return $post;
			$result = $post->getPost($pid);
			if($result) return $result;
		}

		return $result;
	}

	public function show()
	{
		global $current_user;
		echo "    <h1 id=\"top\">" . $this->thread->name . "</h1>\n";
		
		/* // Recursive
		foreach($this->posts as $post) {
			$post->show();
		}
		*/
		
		// Linear
		$firstunread = false;
		foreach($this->posts_linear as $post) {
			if($post->date > $this->thread->lastseen[$current_user->uid] && $firstunread == false) {
				$firstunread = true;
				echo "    <div id=\"firstunread\"></div>\n";
				echo "    <div class=\"unread\">\n";
			}
			$post->show("    ", false);
		}

		if($firstunread == true) {
			echo "    </div>\n";
		}
		
		$this->thread->lastseen[$current_user->uid] = time();

		$this->write();

		echo "    <p><a href=\"#top\">Back to the top</a></p>\n";
	}

	private function recurser($parentpost, $element)
	{
		if($element->tagName != "post") return;

		$post = new Post($element->getAttribute('pid'),
										 $element->getAttribute('title'),
										 $element->getAttribute('user'),
										 $element->getAttribute('date'));

		$this->posts_linear[$post->date . "-" . $post->pid] = $post;

		if($post->pid > $this->maxkey) $this->maxkey = $post->pid;
		
		if($parentpost) $parentpost->add($post);
		else $this->add($post);

		foreach($element->childNodes as $child) {
			if($child->tagName == "post")
				$this->recurser($post, $child);
			if($child->tagName == "message")
				$post->message = $child->textContent;
		}
	}

	private function read()
	{
		$dom = new DomDocument;
		$dom->resolveExternals = FALSE;
		$dom->substituteEntities = FALSE;
		$dom->preserveWhiteSpace = FALSE;
		$dom->load($this->file);
		
		$thread = $dom->documentElement;
		$this->thread = new Thread($thread->getAttribute('tid'),
															 $thread->getAttribute('name'),
															 $thread->getAttribute('lastpost'),
															 $thread->getAttribute('lastseen'));
		foreach($thread->childNodes as $child) {
			$this->recurser(false, $child);
		}

		// The linear list should be sorted.
		sort($this->posts_linear);
	}

	public function Posts($file)
	{
		$this->file = $file;
		if(file_exists($this->file))	$this->read();
	}

}
?>