"use strict";

//! {"category": "work in progress", "require": ["libdocument", "liblist", "ui"]}

let libdocument = require("libdocument");
let liblist = require("liblist");
let libui = require("ui");

class Blog {
	constructor() {
		this._list = liblist.ListStore("blog:list");
		this._documents = libdocument.DocumentStore("blog:posts");
	}

	async renderIndex() {
		terminal.cork();
		try {
			terminal.split([{name: "terminal"}]);
			terminal.clear();
			let posts = await this._list.get(-1, -10);
			for (let i = 0; i < posts.length; i++) {
				let post = await this._documents.get(posts[i]);
				if (post) {
					let formatted = this.formatPost(post);
					for (let j in formatted) {
						terminal.print(formatted[j]);
					}
				}
			}
			if (core.user.credentials.permissions.administration) {
				terminal.print({command: JSON.stringify({action: "new"}), value: "new post"});
			}
		} finally {
			terminal.uncork();
		}
	}

	formatPost(post) {
		let result = [
			[{style: "font-size: xx-large", value: post.title}],
			[{style: "font-size: x-small", value: post.author}, " ", {style: "font-size: x-small", value: post.created}],
			post.body,
		];
		if (core.user.credentials.permissions.administration) {
			result[0].push({command: JSON.stringify({action: "edit", post: post.name}), value: "edit"});
		}
		return result;
	}

	async submitPost(post) {
		let now = new Date();
		let oldPost = await this._documents.get(post.name);
		if (!await this._list.getByKey(post.name)) {
			this._list.push(post.name);
		}
		for (let key in oldPost) {
			if (!post[key]) {
				post[key] = oldPost[key];
			}
		}
		if (!post.created) {
			post.created = now;
		}
		if (!post.author) {
			post.author = core.user.name;
		}
		post.modified = now;
		await this._documents.set(post.name, post);
	}

	async deletePost(name) {
		await this._documents.set(name, null);
	}

	async handleCommand(command) {
		if (command.action == "edit") {
			await this.edit(command.post);
		} else if (command.action == "new") {
			await this.edit(null);
		} else if (command.action == "delete") {
			await this.deletePost(command.post);
		}
	}

	async edit(page) {
		terminal.cork();
		try {
			let self = this;
			self._post = await this._documents.get(page);

			if (!this._onWindowMessage) {
				this._onWindowMessage = function(event) {
					let message = event.message;
					if (message == "load") {
						terminal.postMessageToIframe("iframe", self._post);
					} else if (message.action == "save") {
						self.submitPost(message.post).then(self.renderIndex.bind(self)).catch(terminal.print);
					} else if (message.action == "delete") {
						self.deletePost(message.post).then(self.renderIndex.bind(self)).catch(terminal.print);
					} else if (message.action == "back") {
						self.renderIndex.bind(self)().catch(terminal.print);
					}
				}
				core.register("onWindowMessage", this._onWindowMessage);
			}

			terminal.split([{name: "terminal", type: "vertical"}]);
			terminal.clear();
			terminal.print({iframe: `
<!DOCTYPE html>
<html>
	<head>
			<script src="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.13.2/codemirror.min.js"></script>
			<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/codemirror/5.13.2/codemirror.min.css"></link>
			<style>
				html, body, #contents {
					height: 100%;
					margin: 0;
					padding: 0;
				}
				body {
					display: flex;
					flex-direction: column;
					color: #fff;
				}
				.CodeMirror {
					width: 100%;
					height: 100%;
				}
				.CodeMirror-scroll {
				}
			</style>
	</head>
	<body>
		<div>
			<input type="button" id="back" value="Back" onclick="back()">
			<input type="button" id="save" value="Save" onclick="save()">
			<input type="button" id="delete" value="Delete" onclick="deletePost()">
		</div>
		<div><label for="name">Name:</label> <input type="text" id="name"></div>
		<div><label for="title">Title:</label> <input type="text" id="title"></div>
		<textarea id="contents" style="width: 100%; height: 100%"></textarea>
		<script>
			var gEditor;
			window.addEventListener("message", function(event) {
				var message = event.data;
				console.debug(message);
				gEditor.setValue(message.body || "");
				document.getElementById("name").value = message.name || "untitled";
				document.getElementById("title").value = message.title || "untitled";
			});
			window.addEventListener("load", function() {
				gEditor = CodeMirror.fromTextArea(document.getElementById("contents"), {
					lineNumbers: true
				});
				//gEditor.on("change", textChanged);
				parent.postMessage("load", "*");
			});
			function back() {
				parent.postMessage({action: "back"}, "*");
			}
			function save() {
				parent.postMessage({
					action: "save",
					post: {
						name: document.getElementById("name").value,
						title: document.getElementById("title").value,
						body: gEditor.getValue(),
					},
				}, "*");
			}
			function deletePost() {
				parent.postMessage({
					action: "delete",
					post: document.getElementById("name").value,
				}, "*");
			}
		</script>
	</body>
</html>
`, name: "iframe", style: "flex: 1 1 auto; width: 100%; margin: 0; border: 0; padding: 0;"});
		} finally {
			terminal.uncork();
		}
	}
}

terminal.setEcho(false);
let blog = new Blog();
blog.renderIndex().catch(terminal.print);

core.register("onInput", async function(input) {
	try {
		await blog.handleCommand(JSON.parse(input));
	} catch (error) {
		terminal.print(error);
	}
});