<?php
/**
 * This is the way MOBI files should be created if you want all features (TOC, images).
 *
 * File modified by Dawson for use in eBook Creator
 * Added pagebreaks and a setting to remove table of contents.
 */

class MOBIFile extends ContentProvider {
	const PARAGRAPH = 0;
	const H2 = 1;
	const H3 = 2;
	const IMAGE = 3;
	const PAGEBREAK = 4;
	
	private $settings = array("title" => "Unknown Title", "toc" => true);
	private $parts = array();
	private $images = array();
	
	/**
	 * Get the text data (the "html" code)
	 */
	public function getTextData(){
		$prefix = "<html><head><guide><reference title='CONTENT' type='toc' filepos=0000000000 /></guide></head><body>";
		
		$title = "<h1>".$this->settings["title"]."</h1>";
		
		list($text, $entries) = $this->generateText();
		
		if($this->settings["toc"]) {
			$toc = $this->generateTOC($entries); //Generate TOC to get the right length
			$toc = $this->generateTOC($entries, strlen($prefix)+strlen($toc)+strlen($title)); //Generate the real TOC
		}

		$suffix = "</body></html>";
		
		return $prefix.$toc.$title.$text.$suffix;
	}
	
	/**
	 * Generate the body's text and the chapter entries
	 * @return array($string, $entries) $string is the html data, $entries
	 * contains the level, the title and the position of the titles.
	 */
	public function generateText(){
		$str = "";
		$entries = array();
		
		for($i = 0; $i < sizeof($this->parts); $i++){
			list($type, $data) = $this->parts[$i];
			$id = "title_".$i;
			switch($type){
				case self::PARAGRAPH:
					$str .= "<p>".$data."</p>";
					break;
				case self::PAGEBREAK:
					$str .= '<mbp:pagebreak/>';
					break;
				case self::H2:
					$entries[] = array("level" => 2, "position" => strlen($str), "title" => $data, "id" => $id);
					$str .= "<h2 id='" . $id . "'>".$data."</h2>";
					break;
				case self::H3:
					$entries[] = array("level" => 3, "position" => strlen($str), "title" => $data, "id" => $id);
					$str .= "<h3 id='" . $id . "'>".$data."</h3>";
					break;
				case self::IMAGE:
					$str .= "<img recindex=".str_pad($data+1, 10, "0", STR_PAD_LEFT)." />";
					break;
			}
		}
		return array($str, $entries);
	}
	
	/**
	 * Generate a TOC
	 * @param $entries The entries array generated by generateText
	 * @param $base The zero position
	 */
	public function generateTOC($entries, $base = 0){
		$toc = "<h2>Contents</h2>";
		$toc .= "<blockquote><table summary='Table of Contents'><col/><tbody>";
		for($i = 0, $len = sizeof($entries); $i < $len; $i++){
			$entry = $entries[$i];
			$pos = str_pad($entry["position"]+$base, 10, "0", STR_PAD_LEFT);
			$toc .= "<tr><td><a href='#".$entry["id"]."' filepos='".$pos."'>".$entry["title"]."</a></td></tr>";
		}
		return $toc."</tbody></b></table></blockquote><mbp:pagebreak/>";
	}
	
	/**
	 * Get the file records of the images
	 */
	public function getImages(){
		return $this->images;
	}
	
	/**
	 * Get the metadata
	 */
	public function getMetaData(){
		return $this->settings;
	}
	
	/**
	 * Change the file's settings. For example set("author", "John Doe") or set("title", "The adventures of John Doe").
	 * @param $key Key of the setting to insert.
	 */
	public function set($key, $value){
		$this->settings[$key] = $value;
	}
	
	/**
	 * Get the file's settings.
	 */
	public function get($key){
		return $this->settings[$key];
	}
	
	/**
	 * Append a paragraph of text to the file.
	 * @param string $text The text to insert.
	 */
	public function appendParagraph($text){
		$this->parts[] = array(self::PARAGRAPH, $text);
	}
	
	/**
	 * Append a chapter title (H2)
	 * @param string $title The title to insert.
	 */
	public function appendChapterTitle($title){
		$this->parts[] = array(self::H2, $title);
	}
	
	/**
	 * Append a section title (H3)
	 * @param string $title The title to insert.
	 */
	public function appendSectionTitle($title){
		$this->parts[] = array(self::H3, $title);
	}
	
	public function appendPageBreak() {
		$this->parts[] = array(self::PAGEBREAK, null);
	}

	/**
	 * Append an image.
	 * @param resource $img An image file (for example, created by `imagecreate`)
	 */
	public function appendImage($img){
		$imgIndex = sizeof($this->images);
		$this->images[] = new FileRecord(new Record(ImageHandler::CreateImage($img)));
		$this->parts[] = array(self::IMAGE, $imgIndex);
	}
}