<?php /* -*- Mode: php; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */

global $UTIL_DIR;

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

function isJpeg($file)
{
	$parts = explode(".", $file);
	$suffix = $parts[sizeof($parts) - 1];
	$suffix = strtolower($suffix);
	return $suffix == "jpg" || $suffix == "jpeg";
}

function cleanUp($dir)
{
	$d = opendir($dir);
	while(false !== ($f = readdir($d))) {
		if($f == '.' || $f == '..') continue;
		if(is_dir($f)) cleanUp($dir . "/" . $f);
		else unlink($dir . "/" . $f);
	}
	closedir($d);

	rmdir($dir);
}

class Photo {
	public $id;
	private $path;
  public $title;
	public $image;

  public function write($fp)
  {
    fwrite($fp, "    <photo id=\"" .
					 htmlspecialchars($this->id, ENT_QUOTES, "UTF-8") . "\"\n");
    fwrite($fp, "           title=\"" .
					 htmlspecialchars($this->title, ENT_QUOTES, "UTF-8") . "\"\n");
    fwrite($fp, "           image=\"" .
					 htmlspecialchars($this->image, ENT_QUOTES, "UTF-8") . "\"/>\n");
  }

  public function show($indent, $cat)
  {
		$str = "";
		$str .= $indent."<span class=\"photo\">\n";
		if($cat == "photo") $str .= $indent."  <a href=\"" . $this->path . "/" . $this->image . "\">\n";

		$str .= $indent."  <span class=\"photo_image\">\n";
		$str .= $indent."    <img alt=\"".$this->title."\"\n";
		$str .= $indent."         src=\"?mode=imagecache&amp;uri="
			. $this->path . "/" . $this->image . "&amp;mod=gallery&amp;cat=".$cat."\"/>\n";
		$str .= $indent."  </span>\n";
		if($cat == "photo") $str .= $indent."  </a>\n";
		$str .= $indent."  <span class=\"photo_caption\">" . $this->title . "</span>\n";
		$str .= $indent."</span>\n";
		return $str;
  }

  public function Photo($path, $id, $title, $image)
  {
		$this->path = $path;
		$this->id = $id;
    $this->title = $title;
		$this->image = $image;
  }
}


class Album {
	public $id;
  public $title;
	public $copyright;
	public $enabled;
	public $icon;
	public $photos = array();

	public function add($photo)
	{
		$this->photos[$photo->id] = $photo;
	}

  public function write($fp)
  {
    fwrite($fp, "  <album id=\"" .
	   htmlspecialchars($this->id, ENT_QUOTES, "UTF-8") . "\"\n");
    fwrite($fp, "         title=\"" .
	   htmlspecialchars($this->title, ENT_QUOTES, "UTF-8") . "\"\n");
    fwrite($fp, "         copyright=\"" .
	   htmlspecialchars($this->copyright, ENT_QUOTES, "UTF-8") . "\"\n");
    fwrite($fp, "         icon=\"" .
	   htmlspecialchars($this->icon, ENT_QUOTES, "UTF-8") . "\"\n");
    if($this->enabled) fwrite($fp, "         enabled=\"true\">\n");
    else fwrite($fp, "         enabled=\"false\">\n");
		foreach($this->photos as $photo) {
			$photo->write($fp);
		}
    fwrite($fp, "  </album>\n");
  }

  public function show($indent)
  {
		global $page;

		$str = "";
		$str .= $indent."<span class=\"album\">\n";
		$str .= $indent."  <span class=\"album_title\">" . $this->title . "</span>\n";
		foreach($this->photos as $photo) {
			$str .= $indent."    <a class=\"photo_icon\" href=\"?page=".$page."&amp;a=".$this->id."&amp;p=".$photo->id."\">\n";
			$str .= $photo->show($indent."      ", "albumicon");
			$str .= $indent."    </a>\n";
		}
		$str .= $indent."</span>\n";

		return $str;
  }

	public function showIcon($indent)
	{
		global $page;

		$str = "";

		$str .= $indent."<a class=\"album\" href=\"?page=".$page."&amp;a=".$this->id."\">\n";
		$str .= $indent."  <span class=\"album_title\">".$this->title."</span>\n";
		$str .= $indent."  <span class=\"album_icon\">\n";
		$str .= $this->photos[$this->icon]->show($indent."    ", "albumicon");
		$str .= $indent."  </span>\n";
		$str .= $indent."</a>\n";

		return $str;
	}

	public function showPhoto($indent, $photo)
	{
		global $GLOBALS;

		$album = $this->id;

		$str = "";

		$str = $this->photos[$photo]->show($indent, "photo");

		$str .= $indent."<span class=\"nav_icons\">\n";
		if($this->photos[$photo - 1]) {
		  $str .= $indent."  <a class=\"nav_icon\" href=\"?page=gallery&amp;a=".$album."&amp;p=".($photo-1)."\">\n";
			$str .= $this->photos[$photo - 1]->show($indent."    ", "navicon");
			$str .= $indent."  </a>\n";
		} else {
			$str .= $indent."  <a class=\"nav_icon\" href=\"?page=gallery&amp;a=".$album."\">\n";
			$str .= $indent."    <img alt=\"Stop\" src=\"gfx/stop.png\"/>\n";
			$str .= $indent."  </a>\n";
		}

		$str .= $indent."  <a class=\"nav_icon\" href=\"?page=gallery&amp;a=".$album."\">\n";
		$str .= $indent."    <img alt=\"Home\" src=\"gfx/home.png\"/>\n";
		$str .= $indent."  </a>\n";

		if($this->photos[$photo + 1]) {
		  $str .= $indent."  <a class=\"nav_icon\" href=\"?page=gallery&amp;a=".$album."&amp;p=".($photo+1)."\">\n";
			$str .= $this->photos[$photo + 1]->show($indent."    ", "navicon");
			$str .= $indent."  </a>\n";
		} else {
			$str .= $indent."  <a class=\"nav_icon\" href=\"?page=gallery&amp;a=".$album."\">\n";
			$str .= $indent."    <img alt=\"Stop\" src=\"gfx/stop.png\"/>\n";
			$str .= $indent."  </a>\n";
		}
		$str .= $indent."</span>\n";

		return $str;
	}

	public function getPath()
	{
		global $ALBUMS_DIR;
		return $ALBUMS_DIR . "/" . $this->id;
	}

	public function getNextID()
	{
		$maxid = 0;
    foreach($this->photos as $photo) {
      if($photo->id > $nextid) $maxid = $photo->id;
    }
		return $maxid + 1;
	}

  public function Album($id, $title, $copyright, $icon, $enabled)
  {
		$this->id = $id;
    $this->title = $title;
		$this->copyright = $copyright;
		$this->icon = $icon;
		$this->enabled = $enabled == 'on';
  }
}

function unpackImages($zipfile, $album)
{
	if(is_uploaded_file($zipfile['tmp_name'])) {
		echo "File ". $zipfile['name'] ." uploaded successfully.\n";

		//
		// Unzip file
		//
		// http://dk.php.net/manual/en/book.zip.php
		$zip = new ZipArchive();
		$zip->open($zipfile['tmp_name']);
		$folder = $zipfile['tmp_name'].'.unzip';
		$zip->extractTo($folder);
		
		//
		// Look at EXIF header (Image Description) and move images
		//
		// http://dk.php.net/manual/en/book.exif.php
		if(!file_exists($album->getPath())) mkdir($album->getPath());
		$imagefiles = array();
 		$d = opendir($folder);
		while(false !== ($f = readdir($d))) {
			if(!isJpeg($f)) continue;
			array_push($imagefiles, $f);
		}

		sort($imagefiles);

		foreach($imagefiles as $f) {
			$tags = exif_read_data($folder . "/" . $f, "ANY_TAG");
			rename($folder . "/" . $f, $album->getPath() . "/" . $f);
			$photo = new Photo($album->getPath(), $album->getNextID(), $tags['ImageDescription'], $f);
			$album->add($photo);
		}
		closedir($d);

		//
		// Clean up (recursively)
		//
		cleanUp($folder);
	}
}

class Gallery {

  private $file;
  private $albums = array();

	// Local attributes
	private $maxwidth_navicon;
	private $maxheight_navicon;
	private $maxwidth_icon;
	private $maxheight_icon;
	private $maxwidth_rand;
	private $maxheight_rand;
	private $maxwidth;
	private $maxheight;

  // Admin config
  public $admin_title = "Gallery";
  public $admin_submodules = array("Options" => "options",
																	 "New album" => "new",
																	 "Edit album" => "edit",
																	 "Delete album" => "delete");

  public function admin_new($action, $vars)
  {
		global $ALBUMS_DIR;
    switch($action) {
		case "create":
			$album = new Album($this->getNextID(), $vars['title'], $vars['copyright'], "1", $vars['enabled']);
			unpackImages($_FILES['images'], $album);
			$this->add($album);
			$this->write();
			echo $album->show("", "albumicon");
			break;	

    case "select":
    default:
			$form = new Form("create");
			$form->addWidget(new LineEdit("Album title:", "title"));
			$form->addWidget(new LineEdit("Album copyright:", "copyright"));
			$form->addWidget(new CheckBox("Album enabled:", "enabled"));
			$form->addWidget(new FileUpload("Select image archive:", "images", "application/zip"));
			$form->addWidget(new Button("Create"));
			$form->render();
      break;
    }
  }

  public function admin_options($action, $vars)
  {
    switch($action) {
		case "store":
			$this->maxwidth_navicon = $vars['maxwidth_navicon'];
			$this->maxheight_navicon = $vars['maxheight_navicon'];
			$this->maxwidth_icon = $vars['maxwidth_icon'];
			$this->maxheight_icon = $vars['maxheight_icon'];
			$this->maxwidth_rand = $vars['maxwidth_rand'];
			$this->maxheight_rand = $vars['maxheight_rand'];
			$this->maxwidth = $vars['maxwidth'];
			$this->maxheight = $vars['maxheight'];
			$this->write();
    default:
			$form = new Form("store");
			$form->addWidget(new LineEdit("NavIcon maxwidth:", "maxwidth_navicon", $this->maxwidth_navicon));
			$form->addWidget(new LineEdit("NavIcon maxheight:", "maxheight_navicon", $this->maxheight_navicon));
			$form->addWidget(new LineEdit("Icon maxwidth:", "maxwidth_icon", $this->maxwidth_icon));
			$form->addWidget(new LineEdit("Icon maxheight:", "maxheight_icon", $this->maxheight_icon));
			$form->addWidget(new LineEdit("Random maxwidth:", "maxwidth_rand", $this->maxwidth_rand));
			$form->addWidget(new LineEdit("Random maxheight:", "maxheight_rand", $this->maxheight_rand));
			$form->addWidget(new LineEdit("Image maxwidth:", "maxwidth", $this->maxwidth));
			$form->addWidget(new LineEdit("Image maxheight:", "maxheight", $this->maxheight));
			$form->addWidget(new Button("Update"));
			$form->render();
      break;
    }
  }

  public function admin($sub, $action, $vars)
  {
    switch($sub) {
    case "options":
      $this->admin_options($action, $vars);
      break;
    case "new":
      $this->admin_new($action, $vars);
      break;
    case "edit":
      $this->admin_new($action, $vars);
      break;
    case "delete":
      $this->admin_new($action, $vars);
      break;
    }
  }

	public function showRandomPhoto()
	{
		$str = "";

		srand((float) microtime() * 10000000);
		if(sizeof($this->albums) == 0) return "";
		$album = array_rand($this->albums);
		if(sizeof($this->albums[$album]->photos) == 0) return "";
		$photo = array_rand($this->albums[$album]->photos);

		$str .= "  <a class=\"random_photo_link\" href=\"?page=gallery&amp;a=".$album."&amp;p=".$photo."\">\n";
		$str .= $this->albums[$album]->photos[$photo]->show("    ", "randomimage");
		$str .= "  </a>\n";

		return $str;
	}

	public function showAlbums()
	{
		$str = "";

		$str .= "\n<span class=\"albums\">\n";
		foreach($this->albums as $album) {
			$str .= $album->showIcon("  ");
		}
		$str .= "</span>\n";
		
		return $str;
	}

	public function showPhoto($album, $photo)
	{
		$str = "";

		if($this->albums[$album]) {
			$str .= $this->albums[$album]->showPhoto("  ", $photo);
		}

		return $str;
	}

  public function run($params)
  {
		global $a, $p;

		$str = "";

		$str .= "\n<span class=\"gallery\">\n";
    foreach($params as $param => $value) {
      switch($param) {
			case "random":
				$str .= $this->showRandomPhoto();
				break;

			default:
				if($p != "" && $a != "") $str .= $this->showPhoto($a, $p);
				else if($a != "" &&  $this->albums[$a] && $p == "")
					$str .= $this->albums[$a]->show("  ");
				else $str .= $this->showAlbums();
				break;
      }
    }
		$str .= "</span>\n";

		return $str;
  }

  public function add($album) {
		$this->albums[$album->id] = $album;
  }
	
	public function getNextID()
	{
		$maxid = 0;
    foreach($this->albums as $album) {
      if($album->id > $nextid) $maxid = $album->id;
    }
		return $maxid + 1;
	}

	public function getImageSize($cat)
	{
		switch($cat) {
		case "photo":
			return new ImageSize($this->maxwidth, $this->maxheight);
		case "randomimage":
			return new ImageSize($this->maxwidth_rand, $this->maxheight_rand);
		case "navicon":
			return new ImageSize($this->maxwidth_navicon, $this->maxheight_navicon);
		case "albumicon":
			return new ImageSize($this->maxwidth_icon, $this->maxheight_icon);
		default:
      die(404);
		}
	}

  public function write()
  {
    $fp = fopen($this->file, "w");
    fwrite($fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");

    fwrite($fp, "<gallery maxwidth_navicon=\"".$this->maxwidth_navicon."\"\n");
		fwrite($fp, "         maxheight_navicon=\"".$this->maxheight_navicon."\"\n");
    fwrite($fp, "         maxwidth_icon=\"".$this->maxwidth_icon."\"\n");
		fwrite($fp, "         maxheight_icon=\"".$this->maxheight_icon."\"\n");
		fwrite($fp, "         maxwidth_rand=\"".$this->maxwidth_rand."\"\n");
		fwrite($fp, "         maxheight_rand=\"".$this->maxheight_rand."\"\n");
		fwrite($fp, "         maxwidth=\"".$this->maxwidth."\"\n");
		fwrite($fp, "         maxheight=\"".$this->maxheight."\">\n");
    foreach($this->albums as $album) {
      $album->write($fp);
    }
    fwrite($fp, "</gallery>\n");

    fclose($fp);
  }
	
	private function read()
	{
		$dom = new DomDocument;
		$dom->resolveExternals = FALSE;
		$dom->substituteEntities = FALSE;
		$dom->preserveWhiteSpace = FALSE;
		$dom->load($this->file);
		
		$gallery = $dom->documentElement;

		$this->maxwidth_navicon = $gallery->getAttribute('maxwidth_navicon');
		$this->maxheight_navicon = $gallery->getAttribute('maxheight_navicon');

		$this->maxwidth_icon = $gallery->getAttribute('maxwidth_icon');
		$this->maxheight_icon = $gallery->getAttribute('maxheight_icon');

		$this->maxwidth_rand = $gallery->getAttribute('maxwidth_rand');
		$this->maxheight_rand = $gallery->getAttribute('maxheight_rand');

		$this->maxwidth = $gallery->getAttribute('maxwidth');
		$this->maxheight = $gallery->getAttribute('maxheight');

		foreach($gallery->childNodes as $albumElem) {

			if($albumElem->tagName != "album") continue;

			$album = new Album($albumElem->getAttribute('id'),
												 $albumElem->getAttribute('title'),
												 $albumElem->getAttribute('copyright'),
												 $albumElem->getAttribute('icon'),
												 $albumElem->getAttribute('enabled'));
			
			foreach($albumElem->childNodes as $photoElem) {
				if($photoElem->tagName != "photo") continue;

				$photo = new Photo($album->getPath(),
													 $photoElem->getAttribute('id'),
													 $photoElem->getAttribute('title'),
													 $photoElem->getAttribute('image'));
				$album->add($photo);

			}
			
			$this->add($album);

		}
	}

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

}

function gallery_init()
{
  global $DATA_DIR;
  return new Gallery($DATA_DIR . "/gallery.xml");
}

?>