<?php

class DocumentController {

	public static function browse($pid = 0) {

		$product = new Product($pid);

		return blade("documents", ["product" => $product]);
	}

	public static function show($id) {
		$doc = new Document($id);
		$doc->load();

		return blade("document", [
			"doc" => $doc
		]);
	}

	public static function api_get($id) {
		return new Document($id);
	}

	public static function api_set($id) {
		$doc = new Document($id);
		if ($doc->valid()) {
			foreach ($_POST as $k=>$v) {
				if ($k != "products") {
					$doc->$k = trim($v);
				}
			}
			$doc->save();

			$pids = explode(",", $_POST['products']);
			
			$dpl = DocProduct::find([["document", "=", $id]])->all();;

			foreach ($dpl as $dp) {
				$e = array_search($dp->product, $pids);
				if ($e !== false) {
					unset($pids[$e]);
					continue;
				}
				$dp->delete();
			}

			foreach ($pids as $pid) {
				$dp = new DocProduct;
				$dp->document = $id;
				$dp->product = $pid;
				$dp->save();
			}

			$doc->cache_invalidate("products");

		}
		return $doc;
	}

	public static function api_get_products($id) {
		$doc = new Document($id);
		return $doc->products;
	}

	public static function api_move($id) {
		$doc = new Document($id);
		$from = $_POST['from'];
		$to = $_POST['to'];

		$dp = DocProduct([["document", "=", $id], ["product", "=", $from]])->first();
		if ($dp) {
			$dp->product = $to;
			$dp->save();
		}

		$doc->cache_invalidate("products");

		return [];
	}

	public static function del_docproduct($doc, $prod) {
		$dp = DocProduct::find([["document", "=", $doc], ["product", "=", $prod]])->first();
		if ($dp) {
			$dp->delete();
		}
		return back();
	}

	public static function get_by_id($id) {
		return Document::find([["internal_id", "=", trim($id)]])->first();
	}

	public static function api_merge($id) {
		$from = new Document($id);
		$to = new Document($_POST['to']);

		if ($from->id == $to->id) return [];

		if ($from && $to) {
			$revs = Revision::find([["document", "=", $from->id]]);
			for ($rev = $revs->first(); $rev = $revs->next(); ) {
				$rev->document = $to->id;
				$rev->save();
			}

			$from->delete();
		}
		return new Document($to->id); // Force refresh
	}



	public static function api_drag_drop($_request) {
		$src_id = $_request->post("src_id");
		$dst_id = $_request->post("dst_id");

		$src_type = $_request->post("src_type");
		$dst_type = $_request->post("dst_type");

		$src_extra = $_request->post("src_extra");
		$dst_extra = $_request->post("dst_extra");

		$copy = $_request->post("copy") == "true";

		if (($src_type == "document") && ($dst_type == "document")) {
			// Merge src into dst
			$src = new Document($src_id);
			$dst = new Document($dst_id);

			if ($src->id == $dst->id) return [];

			foreach ($src->revisions as $r) {
				$r->document = $dst->id;
				$r->save();
			}

			$src->delete();
			$dst->cache_invalidate("revisions");
		}

		if (($src_type == "document") && ($dst_type == "product")) {

			if ($copy) {
				$dp = new DocProduct();
				$dp->document = $src_id;
				$dp->product = $dst_id;
				$dp->save();
			} else {

				// Move document into product
				$dpl = DocProduct::find([["document", "=", $src_id], ["product", "=", $src_extra]])->all();
				foreach ($dpl as $dp) {
					$dp->product = $dst_id;
					$dp->save();
				}
				$prod = new Product($src_extra);
				$prod->cache_invalidate("documents");
			}
			$doc = new Document($src_id);
			$doc->cache_invalidate("products");
			$prod = new Product($dst_id);
			$prod->cache_invalidate("documents");
		}

		if (($src_type == "product") && ($dst_type == "product")) {

			if ($src_id == $dst_id) return [];
			// Move product into product
			$sp = new Product($src_id);
			$dp = new Product($dst_id);
			$sp->parent = $dp->id;
			$sp->save();
			$sp->cache_invalidate("parent");
			$sp->cache_invalidate("children");
			$dp->cache_invalidate("parent");
			$dp->cache_invalidate("children");
		}


		return [200, ["didit" => "true"]];
	}

	public static function merge($id) {

		$doc = new Document($id);

		$proc = new Process("pdftk");

		foreach ($doc->revisions as $rev) {
			$proc->arg($rev->path() . "/doc.pdf");
		}

		$nr = new Revision;
		$nr->document = $doc->id;
		$nr->revno = "NEW";
		$nr->save();


		$out = new File($nr->path() . "/doc.pdf");
		$out->parent()->mkdir();

		$proc->arg("output");
		$proc->arg((string)$out);
		$r = $proc->execute();

		if ($r != 0) {
			print("<pre>");
			print_r($proc->stderr());
			print("</pre>");
			exit(0);
		}

		return redirect("/document/" . $doc->id);
	}

	public static function create_overview($id) {

		$job = new GeminiJob($id, "document:$id");
		$jobid = $job->queue();
		flash("success", "Job queued as ID " . $jobid);

		return redirect("/document/" . $id);
	}

	public static function api_get_title_fragment($_request) {
		$q = $_request->post("title");
		$db = DB::getInstance();
		$q1 = $db->query("
			SELECT 
				DISTINCT title 
			FROM (
				SELECT 
					DISTINCT title 
				FROM 
					document 
				WHERE 
					title LIKE :s 
				UNION SELECT 
					DISTINCT subtitle AS title 
				FROM 
					document 
				WHERE 
					subtitle LIKE :s
				UNION SELECT 
					DISTINCT subsubtitle AS title 
				FROM 
					document 
				WHERE subsubtitle LIKE :s
			) AS DERIVED", ["s" => $q . "%"]);
		$o = $db->all($q1);

		if ($o->count() == 0) {
			return [404, "Not Found"];
		}
		if ($o->count() != 1) {
			return [413, "Content Too Large"];
		}
		return $o[0]->title;
	}

	public static function separate($id) {

		$doc = new Document($id);
		$firstprod = $doc->products[0];

		$count = 0;

		foreach ($doc->revisions as $rev) {
			$count++;
			if ($count == 1) {
				continue;
			}

			$newdoc = $doc->duplicate();
			$newdoc->subsubtitle .= " - $count";
			$rev->document = $newdoc->id;
			$rev->save();
		}

		
		return redirect("/documents/" . $firstprod);
	}

	public static function api_get_metadata($id) {
		return DocMeta::find([["document", "=", $id]])->orderBy("metadata")->all();
	}
	
	public static function api_new_metadata($_request, $id) {
		$doc = new Document($id);
		$doc->set_metadata($_request->put("item_id"), "");
		return DocMeta::find([["document", "=", $id]])->orderBy("metadata")->all();
	}

	public static function api_set_metadata($_request, $id, $metadata) {
		$doc = new Document($id);
		$doc->set_metadata($metadata, $_request->post('data'));
		return DocMeta::find([["document", "=", $id]])->orderBy("metadata")->all();
	}

	public static function api_delete_metadata($id, $metadata) {
		$doc = new Document($id);
		$doc->remove_metadata($metadata);
		return DocMeta::find([["document", "=", $id]])->orderBy("metadata")->all();
	}

	public static function api_available_metadata($id) {
		$exist = DocMeta::find([["document", "=", $id]])->orderBy("metadata")->all();
		$metas = MetaType::find()->all();


		$out = new Collection();

		foreach ($metas as $meta) {
			$e = false;
			foreach ($exist as $ex) {
				if ($ex->metadata == $meta->id) {
					$e = true;
					break;
				}
			}

			if (!$e) {
				$cl = new stdClass;
				$cl->key = $meta->id;
				$cl->value = $meta->name;
				$out->push($cl);
			}
		}

		$out->sort("value");

		return $out;
	}

	public static function delete_metadata($id, $metadata) {
		$doc = new Document($id);
		$doc->remove_metadata($metadata);
		return redirect("/document/" . $id);
	}

	public static function api_guess_docid($id) {
		$doc = new Document($id);
		$docid = $doc->guess_docid();

		return new Collection(["id" => $id, "docid" => $docid]);
	}

	public static function download_attachment($id, $filename) {
		$doc = new Document($id);
		$atts = $doc->get_attachments();
		foreach ($atts as $f) {
			if ($f->basename() == $filename) {
				$f->set_header("Content-Disposition", "attachment; filename=\"$filename\"");

				return $f;
			}
		}
		return false;
	}

	public static function upload_attachment($id) {
		$doc = new Document($id);
		return blade("upload.attachment", ["doc" => $doc]);
	}

	public static function do_upload_attachment($_request, $id) {
		$doc = new Document($id);
		mkdir(ROOT . "/attachments/" . $doc->id, 0777);

		$f = 0;
		while (($file = $_request->file("file", $f)) !== false) {
			$nf = new File($file['tmp_name']);
			$nf->rename(ROOT . "/attachments/" . $doc->id . "/" . $file['name']);
			$f++;
		}
		return redirect("/document/" . $doc->id);
	}
}
